You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2017/01/18 13:37:30 UTC

ambari git commit: AMBARI-19611. Add UI UT for alerts (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 61d0f640b -> d7f1e8c00


AMBARI-19611. Add UI UT for alerts (onechiporenko)


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

Branch: refs/heads/trunk
Commit: d7f1e8c00e574e5612f40e286b9795bd1e531259
Parents: 61d0f64
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Wed Jan 18 13:58:43 2017 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Wed Jan 18 15:35:20 2017 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   1 +
 .../alerts/definition_details_controller.js     |  24 ++-
 .../alerts/manage_alert_groups_controller.js    | 194 ++++++++-----------
 .../manage_alert_notifications_controller.js    | 106 +++++-----
 .../app/mappers/alert_definitions_mapper.js     |  16 +-
 ambari-web/app/models/alerts/alert_config.js    |   4 +-
 ambari-web/app/models/alerts/alert_group.js     |   2 +-
 .../app/models/alerts/alert_notification.js     |   4 +-
 .../manage_alert_groups_controller_test.js      |  57 ++++++
 ...anage_alert_notifications_controller_test.js |  10 +
 .../test/models/alerts/alert_config_test.js     |  21 ++
 .../test/models/alerts/alert_group_test.js      |  25 +++
 .../models/alerts/alert_notification_test.js    |  50 +++++
 13 files changed, 313 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index e42c811..d47d558 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -390,6 +390,7 @@ var files = [
   'test/models/alerts/alert_definition_test',
   'test/models/alerts/alert_group_test',
   'test/models/alerts/alert_instance_test',
+  'test/models/alerts/alert_notification_test',
   'test/models/authentication_test',
   'test/models/client_component_test',
   'test/models/cluster_states_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/controllers/main/alerts/definition_details_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/definition_details_controller.js b/ambari-web/app/controllers/main/alerts/definition_details_controller.js
index ea9b5b7..55d7e2b 100644
--- a/ambari-web/app/controllers/main/alerts/definition_details_controller.js
+++ b/ambari-web/app/controllers/main/alerts/definition_details_controller.js
@@ -105,10 +105,9 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
     var lastDayAlertsCount = {};
     data.items.forEach(function (alert) {
       if (!lastDayAlertsCount[alert.AlertHistory.host_name]) {
-        lastDayAlertsCount[alert.AlertHistory.host_name] = 1;
-      } else {
-        lastDayAlertsCount[alert.AlertHistory.host_name] += 1;
+        lastDayAlertsCount[alert.AlertHistory.host_name] = 0;
       }
+      lastDayAlertsCount[alert.AlertHistory.host_name]++;
     });
     this.set('lastDayAlertsCount', lastDayAlertsCount);
   },
@@ -149,14 +148,14 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
     element.set('isEditing', false);
 
     var data = Em.Object.create({});
-    var property_name = "AlertDefinition/" + element.get('name');
-    data.set(property_name, element.get('value'));
-    var alertDefinition_id = this.get('content.id');
+    var propertyName = "AlertDefinition/" + element.get('name');
+    data.set(propertyName, element.get('value'));
+    var alertDefinitionId = this.get('content.id');
     return App.ajax.send({
       name: 'alerts.update_alert_definition',
       sender: this,
       data: {
-        id: alertDefinition_id,
+        id: alertDefinitionId,
         data: data
       }
     });
@@ -180,10 +179,9 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
 
   /**
    * "Delete" button handler
-   * @param {object} event
    * @method deleteAlertDefinition
    */
-  deleteAlertDefinition: function (event) {
+  deleteAlertDefinition: function () {
     var alertDefinition = this.get('content');
     var self = this;
     App.showConfirmationPopup(function () {
@@ -229,7 +227,7 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
       confirmButton: alertDefinition.get('enabled') ? Em.I18n.t('alerts.table.state.enabled.confirm.btn') : Em.I18n.t('alerts.table.state.disabled.confirm.btn')
     });
 
-    return App.showConfirmationFeedBackPopup(function (query) {
+    return App.showConfirmationFeedBackPopup(function () {
       self.toggleDefinitionState(alertDefinition);
     }, bodyMessage);
   },
@@ -286,14 +284,14 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
       header: Em.I18n.t('alerts.actions.editRepeatTolerance.header'),
       primary: Em.I18n.t('common.save'),
       secondary: Em.I18n.t('common.cancel'),
-      inputValue: self.get('content.repeat_tolerance_enabled') ? (self.get('content.repeat_tolerance') || 1) : alertsRepeatTolerance,
+      inputValue: self.get('content.repeat_tolerance_enabled') ? self.get('content.repeat_tolerance') || 1 : alertsRepeatTolerance,
       errorMessage: Em.I18n.t('alerts.actions.editRepeatTolerance.error'),
       isInvalid: function () {
         var intValue = Number(this.get('inputValue'));
         return this.get('inputValue') !== 'DEBUG' && (!validator.isValidInt(intValue) || intValue < 1 || intValue > 99);
       }.property('inputValue'),
       isChanged: function () {
-        return Number(this.get('inputValue')) != alertsRepeatTolerance;
+        return Number(this.get('inputValue')) !== alertsRepeatTolerance;
       }.property('inputValue'),
       doRestoreDefaultValue: function () {
         this.set('inputValue', alertsRepeatTolerance);
@@ -306,7 +304,7 @@ App.MainAlertDefinitionDetailsController = Em.Controller.extend({
         }
         var input = this.get('inputValue');
         self.set('content.repeat_tolerance', input);
-        self.enableRepeatTolerance(input != alertsRepeatTolerance);
+        self.enableRepeatTolerance(input !== alertsRepeatTolerance);
         App.ajax.send({
           name: 'alerts.update_alert_definition',
           sender: self,

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js b/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
index a501a34..ea649b8 100644
--- a/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
+++ b/ambari-web/app/controllers/main/alerts/manage_alert_groups_controller.js
@@ -20,6 +20,35 @@ var App = require('app');
 
 var validator = require('utils/validator');
 
+function stringify(obj, property) {
+  return JSON.stringify(obj.get(property).slice().sort());
+}
+
+function groupsAreNotEqual(group1, group2) {
+  return stringify(group1, 'definitions') !== stringify(group2, 'definitions') ||
+  stringify(group1, 'notifications') !== stringify(group2, 'notifications');
+}
+
+function mapToEmObjects(collection, fields, renamedFields) {
+  var _renamedFields = arguments.length === 3 ? renamedFields : [];
+  return collection.map(function (item) {
+    var ret = Em.Object.create(Em.getProperties(item, fields));
+    _renamedFields.forEach(function (renamedField) {
+      var [realName, newName] = renamedField.split(':');
+      Em.set(ret, newName, Em.get(item, realName));
+    });
+    return ret;
+  });
+}
+
+var AlertGroupClone = Em.Object.extend({
+  displayName: function () {
+    var name = App.config.truncateGroupName(this.get('name'));
+    return this.get('default') ? name + ' Default' : name;
+  }.property('name', 'default'),
+  label: Em.computed.format('{0} ({1})', 'displayName', 'definitions.length')
+});
+
 App.ManageAlertGroupsController = Em.Controller.extend({
 
   name: 'manageAlertGroupsController',
@@ -60,15 +89,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    * @type {App.AlertNotification[]}
    */
   alertNotifications: function () {
-    return this.get('isLoaded') ? App.AlertNotification.find().map(function (target) {
-      return Em.Object.create({
-        name: target.get('name'),
-        id: target.get('id'),
-        description: target.get('description'),
-        type: target.get('type'),
-        global: target.get('global')
-      });
-    }) : [];
+    return this.get('isLoaded') ? mapToEmObjects(App.AlertNotification.find(), ['id', 'name', 'description', 'type', 'global']) : [];
   }.property('isLoaded'),
 
   /**
@@ -97,8 +118,8 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    */
   isDeleteDefinitionsDisabled: function () {
     var selectedGroup = this.get('selectedAlertGroup');
-    return selectedGroup ? (selectedGroup.default || this.get('selectedDefinitions').length === 0) : true;
-  }.property('selectedAlertGroup', 'selectedAlertGroup.definitions.length', 'selectedDefinitions.length'),
+    return selectedGroup ? selectedGroup.default || this.get('selectedDefinitions').length === 0 : true;
+  }.property('selectedAlertGroup.definitions.length', 'selectedDefinitions.length'),
 
   /**
    * observes if any group changed including: group name, newly created group, deleted group, group with definitions/notifications changed
@@ -120,7 +141,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    */
   defsModifiedAlertGroupsObs: function() {
     Em.run.once(this, this.defsModifiedAlertGroupsObsOnce);
-  }.observes('selectedAlertGroup.definitions.@each', 'selectedAlertGroup.definitions.length', 'selectedAlertGroup.notifications.@each', 'selectedAlertGroup.notifications.length', 'alertGroups', 'isLoaded'),
+  }.observes('selectedAlertGroup.definitions.[]', 'selectedAlertGroup.notifications.[]', 'alertGroups', 'isLoaded'),
 
   /**
    * Update <code>defsModifiedAlertGroups</code>-value
@@ -130,7 +151,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    */
   defsModifiedAlertGroupsObsOnce: function() {
     if (!this.get('isLoaded')) {
-      return false;
+      return;
     }
     var groupsToDelete = [];
     var groupsToSet = [];
@@ -147,12 +168,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
       var originalGroup = mappedOriginalGroups[group.get('id')];
       if (originalGroup) {
         // should update definitions or notifications
-        if (JSON.stringify(group.get('definitions').slice().sort()) !== JSON.stringify(originalGroup.get('definitions').slice().sort())
-          || JSON.stringify(group.get('notifications').slice().sort()) !== JSON.stringify(originalGroup.get('notifications').slice().sort())) {
-          groupsToSet.push(group.set('id', originalGroup.get('id')));
-        }
-        else
-        if (group.get('name') !== originalGroup.get('name')) {
+        if (groupsAreNotEqual(group, originalGroup) || group.get('name') !== originalGroup.get('name')) {
           // should update name
           groupsToSet.push(group.set('id', originalGroup.get('id')));
         }
@@ -222,47 +238,24 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    */
   loadAlertGroups: function () {
     var alertGroups = App.AlertGroup.find().map(function (group) {
-      var definitions = group.get('definitions').map(function (def) {
-        return Em.Object.create({
-          name: def.get('name'),
-          serviceName: def.get('serviceName'),
-          componentName: def.get('componentName'),
-          serviceNameDisplay: def.get('service.displayName'),
-          componentNameDisplay: def.get('componentNameFormatted'),
-          label: def.get('label'),
-          id: def.get('id')
-        });
-      });
-
-      var targets = group.get('targets').map(function (target) {
-        return Em.Object.create({
-          name: target.get('name'),
-          id: target.get('id'),
-          description: target.get('description'),
-          type: target.get('type'),
-          global: target.get('global')
-        });
-      });
-
-      return Em.Object.create({
-        id: group.get('id'),
-        name: group.get('name'),
-        default: group.get('default'),
-        displayName: function () {
-          var name = App.config.truncateGroupName(this.get('name'));
-          return this.get('default') ? name + ' Default' : name;
-        }.property('name', 'default'),
-        label: Em.computed.format('{0} ({1})', 'displayName', 'definitions.length'),
-        definitions: definitions,
-        isAddDefinitionsDisabled: group.get('isAddDefinitionsDisabled'),
-        notifications: targets
-      });
+      var definitions = mapToEmObjects(
+        group.get('definitions'),
+        ['name', 'serviceName', 'componentName', 'label', 'id'],
+        ['service.displayName:serviceNameDisplay', 'componentNameFormatted:componentNameDisplay']
+      );
+
+      var targets = mapToEmObjects(group.get('targets'), ['name', 'id', 'description', 'type', 'global']);
+
+      var hash = Em.getProperties(group, ['id', 'name', 'default', 'isAddDefinitionsDisabled']);
+      hash.definitions = definitions;
+      hash.notifications = targets;
+      return AlertGroupClone.create(hash);
     });
     this.setProperties({
       alertGroups: alertGroups,
       isLoaded: true,
       originalAlertGroups: this.copyAlertGroups(alertGroups),
-      selectedAlertGroup: this.get('alertGroups')[0]
+      selectedAlertGroup: alertGroups[0]
     });
   },
 
@@ -332,22 +325,16 @@ App.ManageAlertGroupsController = Em.Controller.extend({
     selectedAlertGroup.get('definitions').forEach(function (def) {
       usedDefinitionsMap[def.name] = true;
     });
-    sharedDefinitions.forEach(function (shared_def) {
-      if (!usedDefinitionsMap[shared_def.get('name')]) {
-        availableDefinitions.pushObject(shared_def);
+    sharedDefinitions.forEach(function (sharedDef) {
+      if (!usedDefinitionsMap[sharedDef.get('name')]) {
+        availableDefinitions.pushObject(sharedDef);
       }
     });
-    return availableDefinitions.map(function (def) {
-      return Em.Object.create({
-        name: def.get('name'),
-        serviceName: def.get('serviceName'),
-        componentName: def.get('componentName'),
-        serviceNameDisplay: def.get('service.displayName'),
-        componentNameDisplay: def.get('componentNameFormatted'),
-        label: def.get('label'),
-        id: def.get('id')
-      });
-    });
+    return mapToEmObjects(
+      availableDefinitions,
+      ['name', 'serviceName', 'componentName', 'label', 'id'],
+      ['service.displayName:serviceNameDisplay', 'componentNameFormatted:componentNameDisplay']
+    );
   },
 
   /**
@@ -359,10 +346,6 @@ App.ManageAlertGroupsController = Em.Controller.extend({
       return false;
     }
     var availableDefinitions = this.getAvailableDefinitions(this.get('selectedAlertGroup'));
-    var popupDescription = {
-      header: Em.I18n.t('alerts.actions.manage_alert_groups_popup.selectDefsDialog.title'),
-      dialogMessage: Em.I18n.t('alerts.actions.manage_alert_groups_popup.selectDefsDialog.message').format(this.get('selectedAlertGroup.displayName'))
-    };
     var validComponents = App.StackServiceComponent.find().map(function (component) {
       return Em.Object.create({
         componentName: component.get('componentName'),
@@ -377,7 +360,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
         selected: false
       });
     });
-    this.launchDefsSelectionDialog(availableDefinitions, [], validServices, validComponents, this.addDefinitionsCallback.bind(this), popupDescription);
+    return this.launchDefsSelectionDialog(availableDefinitions, [], validServices, validComponents);
   },
 
   /**
@@ -385,20 +368,20 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    * @method launchDefsSelectionDialog
    * @return {App.ModalPopup}
    */
-  launchDefsSelectionDialog: function (initialDefs, selectedDefs, validServices, validComponents, callback, popupDescription) {
-
+  launchDefsSelectionDialog: function (initialDefs, selectedDefs, validServices, validComponents) {
+    var self = this;
     return App.ModalPopup.show({
 
       classNames: [ 'common-modal-wrapper' ],
 
       modalDialogClasses: ['modal-lg'],
 
-      header: popupDescription.header,
+      header: Em.I18n.t('alerts.actions.manage_alert_groups_popup.selectDefsDialog.title'),
 
       /**
        * @type {string}
        */
-      dialogMessage: popupDescription.dialogMessage,
+      dialogMessage: Em.I18n.t('alerts.actions.manage_alert_groups_popup.selectDefsDialog.message').format(this.get('selectedAlertGroup.displayName')),
 
       /**
        * @type {string|null}
@@ -417,7 +400,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
           this.set('warningMessage', Em.I18n.t('alerts.actions.manage_alert_groups_popup.selectDefsDialog.message.warning'));
           return;
         }
-        callback(arrayOfSelectedDefs);
+        self.addDefinitionsCallback(arrayOfSelectedDefs);
         this.hide();
       },
 
@@ -428,7 +411,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
       disablePrimary: Em.computed.not('isLoaded'),
 
       onSecondary: function () {
-        callback(null);
+        self.addDefinitionsCallback(null);
         this.hide();
       },
 
@@ -481,7 +464,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
   postNewAlertGroup: function (newAlertGroupData, callback) {
     // create a new group with name , definition and notifications
     var data = {
-      'name': newAlertGroupData.get('name')
+      name: newAlertGroupData.get('name')
     };
     if (newAlertGroupData.get('definitions').length > 0) {
       data.definitions = newAlertGroupData.get('definitions').mapProperty('id');
@@ -523,10 +506,10 @@ App.ManageAlertGroupsController = Em.Controller.extend({
     var sendData = {
       name: 'alert_groups.update',
       data: {
-        "group_id": alertGroup.id,
-        'name': alertGroup.get('name'),
-        'definitions': alertGroup.get('definitions').mapProperty('id'),
-        'targets': alertGroup.get('notifications').mapProperty('id')
+        group_id: alertGroup.id,
+        name: alertGroup.get('name'),
+        definitions: alertGroup.get('definitions').mapProperty('id'),
+        targets: alertGroup.get('notifications').mapProperty('id')
       },
       success: 'successFunction',
       error: 'errorFunction',
@@ -556,7 +539,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
     var sendData = {
       name: 'alert_groups.delete',
       data: {
-        "group_id": alertGroup.id
+        group_id: alertGroup.id
       },
       success: 'successFunction',
       error: 'errorFunction',
@@ -631,24 +614,19 @@ App.ManageAlertGroupsController = Em.Controller.extend({
        * @type {string|null}
        */
       warningMessage: function () {
-        var warningMessage = '';
         var originalGroup = self.get('selectedAlertGroup');
         var groupName = this.get('alertGroupName').trim();
 
         if (originalGroup.get('name').trim() === groupName) {
-          warningMessage = Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
+          return Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
+        }
+        if (self.get('alertGroups').mapProperty('displayName').contains(groupName)) {
+          return Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
         }
-        else {
-          if (self.get('alertGroups').mapProperty('displayName').contains(groupName)) {
-            warningMessage = Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
-          }
-          else {
-            if (groupName && !validator.isValidAlertGroupName(groupName)) {
-              warningMessage = Em.I18n.t("form.validator.alertGroupName");
-            }
-          }
+        if (groupName && !validator.isValidAlertGroupName(groupName)) {
+          return Em.I18n.t("form.validator.alertGroupName");
         }
-        return warningMessage;
+        return '';
       }.property('alertGroupName'),
 
       /**
@@ -672,7 +650,7 @@ App.ManageAlertGroupsController = Em.Controller.extend({
    * @method addAlertGroup
    */
   addAlertGroup: function (duplicated) {
-    duplicated = (duplicated === true);
+    duplicated = duplicated === true;
     var self = this;
     var popup = App.ModalPopup.show({
 
@@ -696,17 +674,14 @@ App.ManageAlertGroupsController = Em.Controller.extend({
        * @type {string}
        */
       warningMessage: function () {
-        var warningMessage = '';
         var groupName = this.get('alertGroupName').trim();
         if (self.get('alertGroups').mapProperty('displayName').contains(groupName)) {
-          warningMessage = Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
+          return Em.I18n.t("alerts.actions.manage_alert_groups_popup.addGroup.exist");
         }
-        else {
-          if (groupName && !validator.isValidAlertGroupName(groupName)) {
-            warningMessage = Em.I18n.t("form.validator.alertGroupName");
-          }
+        if (groupName && !validator.isValidAlertGroupName(groupName)) {
+          return Em.I18n.t("form.validator.alertGroupName");
         }
-        return warningMessage;
+        return '';
       }.property('alertGroupName'),
 
       /**
@@ -716,14 +691,9 @@ App.ManageAlertGroupsController = Em.Controller.extend({
       disablePrimary: Em.computed.or('alertGroupNameIsEmpty', 'warningMessage'),
 
       onPrimary: function () {
-        var newAlertGroup = Em.Object.create({
+        var newAlertGroup = AlertGroupClone.create({
           name: this.get('alertGroupName').trim(),
           default: false,
-          displayName: function () {
-            var name = App.config.truncateGroupName(this.get('name'));
-            return this.get('default') ? name + ' Default' : name;
-          }.property('name', 'default'),
-          label: Em.computed.format('{0} ({1})', 'displayName', 'definitions.length'),
           definitions: duplicated ? self.get('selectedAlertGroup.definitions').slice(0) : [],
           notifications: self.get('alertGlobalNotifications'),
           isAddDefinitionsDisabled: false

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js b/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js
index 8501678..f470f08 100644
--- a/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js
+++ b/ambari-web/app/controllers/main/alerts/manage_alert_notifications_controller.js
@@ -211,22 +211,23 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
   newCustomProperty: {name: '', value: ''},
 
   /**
+   * @type {string[]}
+   */
+  customPropertyNames: Em.computed.mapBy('inputFields.customProperties', 'name'),
+
+  /**
    * Check if custom property name exists in the <code>inputFields.customProperties</code>
    *
    * @type {boolean}
    */
-  isNewCustomPropertyExists: function () {
-    return this.get('inputFields.customProperties').mapProperty('name').contains(this.get('newCustomProperty.name'));
-  }.property('newCustomProperty.name'),
+  isNewCustomPropertyExists: Em.computed.existsInByKey('newCustomProperty.name', 'customPropertyNames'),
 
   /**
    * Check if custom property name exists in the <code>ignoredCustomProperties</code>
    *
    * @type {boolean}
    */
-  isNewCustomPropertyIgnored: function () {
-    return this.get('ignoredCustomProperties').contains(this.get('newCustomProperty.name'));
-  }.property('newCustomProperty.name'),
+  isNewCustomPropertyIgnored: Em.computed.existsInByKey('newCustomProperty.name', 'ignoredCustomProperties'),
 
   /**
    * Check if custom property name is valid according to the <code>validator.isValidConfigKey</code>
@@ -403,24 +404,25 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
     var inputFields = this.get('inputFields');
     var selectedAlertNotification = this.get('selectedAlertNotification');
     var methodValue = this.getNotificationTypeText(selectedAlertNotification.get('type'));
+      var properties = selectedAlertNotification.get('properties');
     inputFields.set('name.value', (addCopyToName ? 'Copy of ' : '') + selectedAlertNotification.get('name'));
     inputFields.set('groups.value', selectedAlertNotification.get('groups').toArray());
-    inputFields.set('email.value', selectedAlertNotification.get('properties')['ambari.dispatch.recipients'] ?
-      selectedAlertNotification.get('properties')['ambari.dispatch.recipients'].join(', ') : '');
-    inputFields.set('SMTPServer.value', selectedAlertNotification.get('properties')['mail.smtp.host']);
-    inputFields.set('SMTPPort.value', selectedAlertNotification.get('properties')['mail.smtp.port']);
-    inputFields.set('SMTPUseAuthentication.value', selectedAlertNotification.get('properties')['mail.smtp.auth'] !== "false");
-    inputFields.set('SMTPUsername.value', selectedAlertNotification.get('properties')['ambari.dispatch.credential.username']);
-    inputFields.set('SMTPPassword.value', selectedAlertNotification.get('properties')['ambari.dispatch.credential.password']);
-    inputFields.set('retypeSMTPPassword.value', selectedAlertNotification.get('properties')['ambari.dispatch.credential.password']);
-    inputFields.set('SMTPSTARTTLS.value', selectedAlertNotification.get('properties')['mail.smtp.starttls.enable'] !== "false");
-    inputFields.set('emailFrom.value', selectedAlertNotification.get('properties')['mail.smtp.from']);
-    inputFields.set('version.value', selectedAlertNotification.get('properties')['ambari.dispatch.snmp.version']);
-    inputFields.set('OIDs.value', selectedAlertNotification.get('properties')['ambari.dispatch.snmp.oids.trap']);
-    inputFields.set('community.value', selectedAlertNotification.get('properties')['ambari.dispatch.snmp.community']);
-    inputFields.set('host.value', selectedAlertNotification.get('properties')['ambari.dispatch.recipients'] ?
-      selectedAlertNotification.get('properties')['ambari.dispatch.recipients'].join(', ') : '');
-    inputFields.set('port.value', selectedAlertNotification.get('properties')['ambari.dispatch.snmp.port']);
+    inputFields.set('email.value', properties['ambari.dispatch.recipients'] ?
+      properties['ambari.dispatch.recipients'].join(', ') : '');
+    inputFields.set('SMTPServer.value', properties['mail.smtp.host']);
+    inputFields.set('SMTPPort.value', properties['mail.smtp.port']);
+    inputFields.set('SMTPUseAuthentication.value', properties['mail.smtp.auth'] !== "false");
+    inputFields.set('SMTPUsername.value', properties['ambari.dispatch.credential.username']);
+    inputFields.set('SMTPPassword.value', properties['ambari.dispatch.credential.password']);
+    inputFields.set('retypeSMTPPassword.value', properties['ambari.dispatch.credential.password']);
+    inputFields.set('SMTPSTARTTLS.value', properties['mail.smtp.starttls.enable'] !== "false");
+    inputFields.set('emailFrom.value', properties['mail.smtp.from']);
+    inputFields.set('version.value', properties['ambari.dispatch.snmp.version']);
+    inputFields.set('OIDs.value', properties['ambari.dispatch.snmp.oids.trap']);
+    inputFields.set('community.value', properties['ambari.dispatch.snmp.community']);
+    inputFields.set('host.value', properties['ambari.dispatch.recipients'] ?
+      properties['ambari.dispatch.recipients'].join(', ') : '');
+    inputFields.set('port.value', properties['ambari.dispatch.snmp.port']);
     inputFields.set('severityFilter.value', selectedAlertNotification.get('alertStates'));
     inputFields.set('global.value', selectedAlertNotification.get('global'));
     inputFields.set('allGroups.value', selectedAlertNotification.get('global') ? 'all' : 'custom');
@@ -429,7 +431,6 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
     inputFields.set('description.value', selectedAlertNotification.get('description'));
     inputFields.set('method.value', methodValue);
     inputFields.get('customProperties').clear();
-    var properties = selectedAlertNotification.get('properties');
     var ignoredCustomProperties = this.get('ignoredCustomProperties');
     Em.keys(properties).forEach(function (k) {
       if (ignoredCustomProperties.contains(k)) return;
@@ -502,34 +503,18 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
           if (newName && !this.get('currentName')) {
             this.set('currentName', newName);
           }
-          if (isEdit) {
-            // edit current alert notification
-            if (!newName) {
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.empty');
-            } else if (newName && newName !== this.get('currentName') && self.get('alertNotifications').mapProperty('name').contains(newName)) {
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.existed');
-            } else if (newName && !validator.isValidAlertNotificationName(newName)){
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('form.validator.alertNotificationName');
-            } else {
-              this.set('nameError', false);
-            }
+          var nameExistsCondition = isEdit ? newName && newName !== this.get('currentName') : !!newName;
+          if (!newName) {
+            this.set('nameError', true);
+            errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.empty');
+          } else if (nameExistsCondition && self.get('alertNotifications').mapProperty('name').contains(newName)) {
+            this.set('nameError', true);
+            errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.existed');
+          } else if (newName && !validator.isValidAlertNotificationName(newName)){
+            this.set('nameError', true);
+            errorMessage = Em.I18n.t('form.validator.alertNotificationName');
           } else {
-            // add new alert notification
-            if (!newName) {
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.empty');
-            } else if (newName && self.get('alertNotifications').mapProperty('name').contains(newName)) {
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('alerts.actions.manage_alert_notifications_popup.error.name.existed');
-            } else if (newName && !validator.isValidAlertNotificationName(newName)){
-              this.set('nameError', true);
-              errorMessage = Em.I18n.t('form.validator.alertNotificationName');
-            } else {
-              this.set('nameError', false);
-            }
+            this.set('nameError', false);
           }
           this.set('controller.inputFields.name.errorMsg', errorMessage);
         }.observes('controller.inputFields.name.value'),
@@ -656,7 +641,7 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
          * @method selectAllGroups
          */
         selectAllGroups: function () {
-          if (this.get('controller.inputFields.allGroups.value') == 'custom') {
+          if (this.get('controller.inputFields.allGroups.value') === 'custom') {
             this.set('groupSelect.selection', this.get('groupSelect.content').slice());
           }
         },
@@ -666,7 +651,7 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
          * @method clearAllGroups
          */
         clearAllGroups: function () {
-          if (this.get('controller.inputFields.allGroups.value') == 'custom') {
+          if (this.get('controller.inputFields.allGroups.value') === 'custom') {
             this.set('groupSelect.selection', []);
           }
         },
@@ -737,6 +722,10 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
         } else {
           self.createAlertNotification(apiObject);
         }
+      },
+      hide: function () {
+        self.set('createEditPopup', null);
+        return this._super(...arguments);
       }
     });
     this.set('createEditPopup', createEditPopup);
@@ -797,9 +786,9 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
 
   getNotificationType: function(text) {
     var notificationType = text;
-    if(notificationType == "Custom SNMP") {
+    if(notificationType === "Custom SNMP") {
       notificationType = "SNMP";
-    } else if(notificationType == "SNMP") {
+    } else if(notificationType === "SNMP") {
       notificationType = "AMBARI_SNMP";
     }
     return notificationType;
@@ -807,9 +796,9 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
 
   getNotificationTypeText: function(notificationType) {
     var notificationTypeText = notificationType;
-    if(notificationType == "SNMP") {
+    if(notificationType === "SNMP") {
       notificationTypeText = "Custom SNMP";
-    } else if(notificationType == "AMBARI_SNMP") {
+    } else if(notificationType === "AMBARI_SNMP") {
       notificationTypeText = "SNMP";
     }
     return notificationTypeText;
@@ -936,14 +925,13 @@ App.ManageAlertNotificationsController = Em.Controller.extend({
    * @method enableOrDisableAlertNotification
    */
   enableOrDisableAlertNotification: function (e) {
-    var enabled = (e.context === "disable")?false:true;
     return App.ajax.send({
       name: 'alerts.update_alert_notification',
       sender: this,
       data: {
         data: {
-          "AlertTarget": {
-            "enabled": enabled
+          AlertTarget: {
+            enabled: e.context !== "disable"
           }
         },
         id: this.get('selectedAlertNotification.id')

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/mappers/alert_definitions_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/alert_definitions_mapper.js b/ambari-web/app/mappers/alert_definitions_mapper.js
index cd4e738..c400b89 100644
--- a/ambari-web/app/mappers/alert_definitions_mapper.js
+++ b/ambari-web/app/mappers/alert_definitions_mapper.js
@@ -125,19 +125,11 @@ App.alertDefinitionsMapper = App.QuickDataMapper.create({
 
         var convertedParameters = [];
         var sourceParameters = item.AlertDefinition.source.parameters;
-        if (Array.isArray(sourceParameters)) {
+        if (Ember.isArray(sourceParameters)) {
           sourceParameters.forEach(function (parameter) {
-            convertedParameters.push({
-              id: item.AlertDefinition.id + parameter.name,
-              name: parameter.name,
-              display_name: parameter.display_name,
-              units: parameter.units,
-              value: parameter.value,
-              description: parameter.description,
-              type: parameter.type,
-              threshold: parameter.threshold,
-              visibility: parameter.visibility
-            });
+            let hash = Em.getProperties(parameter, ['name', 'display_name', 'units', 'value', 'description', 'type', 'threshold', 'visibility']);
+            hash.id = item.AlertDefinition.id + parameter.name;
+            convertedParameters.push(hash);
           });
         }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/models/alerts/alert_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alerts/alert_config.js b/ambari-web/app/models/alerts/alert_config.js
index 1af02fc..a951826 100644
--- a/ambari-web/app/models/alerts/alert_config.js
+++ b/ambari-web/app/models/alerts/alert_config.js
@@ -179,7 +179,7 @@ App.AlertConfigProperties = {
     displayType: 'select',
     apiProperty: 'service_name',
     apiFormattedValue: function () {
-      return this.get('value') == 'CUSTOM' ? this.get('value') : App.StackService.find().findProperty('displayName', this.get('value')).get('serviceName');
+      return this.get('value') === 'CUSTOM' ? this.get('value') : App.StackService.find().findProperty('displayName', this.get('value')).get('serviceName');
     }.property('value'),
     change: function () {
       this.set('property.value', true);
@@ -193,7 +193,7 @@ App.AlertConfigProperties = {
     displayType: 'select',
     apiProperty: 'component_name',
     apiFormattedValue: function () {
-      return this.get('value') == 'No component' ? this.get('value') : App.StackServiceComponent.find().findProperty('displayName', this.get('value')).get('componentName');
+      return this.get('value') === 'No component' ? this.get('value') : App.StackServiceComponent.find().findProperty('displayName', this.get('value')).get('componentName');
     }.property('value')
   }),
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/models/alerts/alert_group.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alerts/alert_group.js b/ambari-web/app/models/alerts/alert_group.js
index 4f40ccf..49a850f 100644
--- a/ambari-web/app/models/alerts/alert_group.js
+++ b/ambari-web/app/models/alerts/alert_group.js
@@ -56,7 +56,7 @@ App.AlertGroup = DS.Model.extend({
    */
   displayName: function () {
     var name = App.config.truncateGroupName(this.get('name'));
-    return this.get('default') ? (name + ' Default') : name;
+    return this.get('default') ? name + ' Default' : name;
   }.property('name', 'default'),
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/app/models/alerts/alert_notification.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alerts/alert_notification.js b/ambari-web/app/models/alerts/alert_notification.js
index e503c6b..edfbff9 100644
--- a/ambari-web/app/models/alerts/alert_notification.js
+++ b/ambari-web/app/models/alerts/alert_notification.js
@@ -26,8 +26,8 @@ App.AlertNotification = DS.Model.extend({
   groups: DS.hasMany('App.AlertGroup'),
   global: DS.attr('boolean'),
   enabled: DS.attr('boolean'),
-  displayName: Ember.computed('enabled', function() {
-    return (this.get('enabled') === true)?this.get('name'): this.get('name') + ' (Disabled)';
+  displayName: Ember.computed('enabled', 'name', function() {
+    return this.get('name') + (this.get('enabled') === true ? '' : ' (Disabled)');
   }),
 
   properties: {},

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/test/controllers/main/alerts/manage_alert_groups_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/alerts/manage_alert_groups_controller_test.js b/ambari-web/test/controllers/main/alerts/manage_alert_groups_controller_test.js
index 45c2a4c..2c58017 100644
--- a/ambari-web/test/controllers/main/alerts/manage_alert_groups_controller_test.js
+++ b/ambari-web/test/controllers/main/alerts/manage_alert_groups_controller_test.js
@@ -202,5 +202,62 @@ describe('App.ManageAlertGroupsController', function () {
 
   });
 
+  App.TestAliases.testAsComputedAnd(getController(), 'isDefsModified', ['isLoaded', 'isDefsModifiedAlertGroups']);
+
+  App.TestAliases.testAsComputedOr(getController(), 'isDefsModifiedAlertGroups', ['defsModifiedAlertGroups.toSet.length', 'defsModifiedAlertGroups.toCreate.length', 'defsModifiedAlertGroups.toDelete.length'])
+
+  describe('#addAlertGroup', function () {
+
+    function getAppGroupPopup() {
+      var c = getController();
+      c.addAlertGroup();
+      return c.get('addGroupPopup');
+    }
+
+    App.TestAliases.testAsComputedOr(getAppGroupPopup(), 'disablePrimary', ['alertGroupNameIsEmpty', 'warningMessage']);
+
+  });
+
+  describe('#renameAlertGroup', function () {
+
+    function getRenamePopup() {
+      var c = getController();
+      c.renameAlertGroup();
+      return c.get('renameGroupPopup');
+    }
+
+    App.TestAliases.testAsComputedOr(getRenamePopup(), 'disablePrimary', ['alertGroupNameIsEmpty', 'warningMessage']);
+
+  });
+
+  describe('#alertNotifications', function () {
+    var alertNotifications;
+    beforeEach(function () {
+      sinon.stub(App.AlertNotification, 'find').returns([
+        Em.Object.create({id: 1, name: 'n1', description: 'n1d', type: 'EMAIL', global: true}),
+        Em.Object.create({id: 2, name: 'n2', description: 'n2d', type: 'SNMP', global: false})
+      ]);
+      manageAlertGroupsController.set('isLoaded', true);
+      alertNotifications = manageAlertGroupsController.get('alertNotifications');
+    });
+
+    afterEach(function () {
+      App.AlertNotification.find.restore();
+    });
+
+    it('should be mapped from App.AlertNotification (1)', function () {
+      expect(alertNotifications).to.have.property('length').to.be.equal(2);
+    });
+
+    it('should be mapped from App.AlertNotification (2)', function () {
+      expect(JSON.parse(JSON.stringify(alertNotifications[0]))).to.be.eql({id: 1, name: 'n1', description: 'n1d', type: 'EMAIL', global: true});
+    });
+
+    it('should be mapped from App.AlertNotification (3)', function () {
+      expect(JSON.parse(JSON.stringify(alertNotifications[1]))).to.be.eql({id: 2, name: 'n2', description: 'n2d', type: 'SNMP', global: false});
+    });
+
+  });
+
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/test/controllers/main/alerts/manage_alert_notifications_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/alerts/manage_alert_notifications_controller_test.js b/ambari-web/test/controllers/main/alerts/manage_alert_notifications_controller_test.js
index d63dcb8..15b4da3 100644
--- a/ambari-web/test/controllers/main/alerts/manage_alert_notifications_controller_test.js
+++ b/ambari-web/test/controllers/main/alerts/manage_alert_notifications_controller_test.js
@@ -1022,6 +1022,10 @@ describe('App.ManageAlertNotificationsController', function () {
 
       });
 
+      App.TestAliases.testAsComputedEqualProperties(getBodyClass(), 'allGroupsSelected', 'groupSelect.selection.length', 'groupSelect.content.length');
+
+      App.TestAliases.testAsComputedEqualProperties(getBodyClass(), 'allSeveritySelected', 'severitySelect.selection.length', 'severitySelect.content.length');
+
     });
 
   });
@@ -1330,4 +1334,10 @@ describe('App.ManageAlertNotificationsController', function () {
 
   });
 
+  App.TestAliases.testAsComputedMapBy(getController(), 'customPropertyNames', 'inputFields.customProperties', 'name');
+
+  App.TestAliases.testAsComputedExistsInByKey(getController(), 'isNewCustomPropertyExists', 'newCustomProperty.name', 'customPropertyNames', ['customA', 'customB']);
+
+  App.TestAliases.testAsComputedExistsInByKey(getController(), 'isNewCustomPropertyIgnored', 'newCustomProperty.name', 'ignoredCustomProperties', ['customA', 'customB']);
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/test/models/alerts/alert_config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/alerts/alert_config_test.js b/ambari-web/test/models/alerts/alert_config_test.js
index 74a91f4..78a6b59 100644
--- a/ambari-web/test/models/alerts/alert_config_test.js
+++ b/ambari-web/test/models/alerts/alert_config_test.js
@@ -22,6 +22,18 @@ require('models/alerts/alert_config');
 
 var model;
 
+describe('App.AlertConfigProperty', function () {
+
+  function getConfigProperty() {
+    return App.AlertConfigProperty.create();
+  }
+
+  App.TestAliases.testAsComputedNotExistsIn(getConfigProperty(), 'isPreLabeled', 'displayType', ['radioButton']);
+
+  App.TestAliases.testAsComputedAlias(getConfigProperty(), 'apiFormattedValue', 'value');
+
+});
+
 describe('App.AlertConfigProperties', function () {
 
   describe('Parameter', function () {
@@ -399,4 +411,13 @@ describe('App.AlertConfigProperties', function () {
 
   });
 
+  describe('App.AlertConfigProperties.FormatString', function () {
+    function getFormatStringConfig() {
+      return App.AlertConfigProperties.FormatString.create();
+    }
+
+    App.TestAliases.testAsComputedIfThenElse(getFormatStringConfig(), 'apiProperty', 'isJMXMetric', 'source.jmx.value', 'source.ganglia.value');
+
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/test/models/alerts/alert_group_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/alerts/alert_group_test.js b/ambari-web/test/models/alerts/alert_group_test.js
index 036a32d..6f64b7a 100644
--- a/ambari-web/test/models/alerts/alert_group_test.js
+++ b/ambari-web/test/models/alerts/alert_group_test.js
@@ -22,8 +22,33 @@ function getModel() {
   return App.AlertGroup.createRecord();
 }
 
+var model;
+
 describe('App.AlertGroup', function() {
 
+  beforeEach(function () {
+    model = getModel();
+  });
+
   App.TestAliases.testAsComputedAlias(getModel(), 'isAddDefinitionsDisabled', 'default', 'boolean');
 
+  describe('#displayName', function () {
+
+    [
+      {name: 'abc', default: true, e: 'abc Default'},
+      {name: 'abc', default: false, e: 'abc'},
+      {name: '12345678901234567890', default: true, e: '123456789...234567890 Default'},
+      {name: '12345678901234567890', default: false, e: '123456789...234567890'},
+    ].forEach(function (test) {
+      it(test.name + ' ' + test.default, function () {
+        model.setProperties({
+          name: test.name,
+          default: test.default
+        });
+        expect(model.get('displayName')).to.be.equal(test.e);
+      });
+    });
+
+  });
+
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/d7f1e8c0/ambari-web/test/models/alerts/alert_notification_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/alerts/alert_notification_test.js b/ambari-web/test/models/alerts/alert_notification_test.js
new file mode 100644
index 0000000..a03fd4e
--- /dev/null
+++ b/ambari-web/test/models/alerts/alert_notification_test.js
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+var model;
+
+function getModel() {
+  return App.AlertNotification.createRecord();
+}
+
+describe('App.AlertNotification', function () {
+
+  beforeEach(function () {
+    model = getModel();
+  });
+
+  describe('#displayName', function () {
+
+    [
+      {name: 'abc', enabled: true, e: 'abc'},
+      {name: 'abc', enabled: false, e: 'abc (Disabled)'},
+    ].forEach(function (test) {
+      it(test.name + ' ' + test.enabled, function () {
+        model.setProperties({
+          name: test.name,
+          enabled: test.enabled
+        });
+        expect(model.get('displayName')).to.be.equal(test.e);
+      });
+    });
+
+  });
+
+});