Repository: ambari
Updated Branches:
  refs/heads/trunk 0a6a64477 -> 1b6002a5e


AMBARI-8526. Alerts UI: Create Notification dialog should have ability to add 
extra configs (onechiporenko)


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

Branch: refs/heads/trunk
Commit: 1b6002a5e6f12c142185f8a0a827b944c267290a
Parents: 0a6a644
Author: Oleg Nechiporenko <onechipore...@apache.org>
Authored: Wed Dec 3 18:15:34 2014 +0200
Committer: Oleg Nechiporenko <onechipore...@apache.org>
Committed: Wed Dec 3 18:15:34 2014 +0200

----------------------------------------------------------------------
 .../assets/data/alerts/alertNotifications.json  |  45 ++---
 .../manage_alert_notifications_controller.js    | 163 +++++++++++++++++--
 ambari-web/app/messages.js                      |   4 +
 ambari-web/app/styles/alerts.less               |   5 +
 ...ustom_config_to_alert_notification_popup.hbs |  42 +++++
 .../main/alerts/create_alert_notification.hbs   |  13 ++
 ambari-web/app/utils/ajax/ajax.js               |   4 +-
 ambari-web/app/utils/validator.js               |   8 +-
 ...anage_alert_notifications_controller_test.js | 128 ++++++++++++++-
 9 files changed, 349 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/assets/data/alerts/alertNotifications.json
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/data/alerts/alertNotifications.json 
b/ambari-web/app/assets/data/alerts/alertNotifications.json
index 8e19655..4e71e1c 100644
--- a/ambari-web/app/assets/data/alerts/alertNotifications.json
+++ b/ambari-web/app/assets/data/alerts/alertNotifications.json
@@ -1,45 +1,24 @@
 {
-  "href" : "http://c6407.ambari.apache.org:8080/api/v1/alert_targets?fields=*";,
+  "href" : "http://host:8080/api/v1/alert_targets?fields=*";,
   "items" : [
     {
-      "href" : "http://c6407.ambari.apache.org:8080/api/v1/alert_targets/1";,
+      "href" : "http://host:8080/api/v1/alert_targets/1";,
       "AlertTarget" : {
-        "description" : "The Admins",
+        "alert_states" : [
+          "UNKNOWN",
+          "CRITICAL",
+          "OK",
+          "WARNING"
+        ],
+        "description" : "123",
         "id" : 1,
-        "name" : "Administrators",
+        "name" : "123",
         "notification_type" : "EMAIL",
         "properties" : {
-          "mail.smtp.from" : "amb...@repo.ambari.apache.org",
-          "ambari.dispatch.credential.username" : "ambari",
-          "mail.smtp.host" : "repo.ambari.apache.org",
-          "mail.smtp.port" : "25",
-          "mail.smtp.auth" : "true",
-          "ambari.dispatch.credential.password" : "password",
           "ambari.dispatch.recipients" : [
-            "amb...@repo.ambari.apache.org"
+            "1...@123.com"
           ],
-          "mail.smtp.tarttls.enable" : "false"
-        }
-      }
-    },
-    {
-      "href" : "http://c6407.ambari.apache.org:8080/api/v1/alert_targets/2";,
-      "AlertTarget" : {
-        "description" : "another user",
-        "id" : 2,
-        "name" : "user1",
-        "notification_type" : "EMAIL",
-        "properties" : {
-          "mail.smtp.from" : "amb...@repo.ambari.apache.org",
-          "ambari.dispatch.credential.username" : "ambari",
-          "mail.smtp.host" : "repo.ambari.apache.org",
-          "mail.smtp.port" : "25",
-          "mail.smtp.auth" : "true",
-          "ambari.dispatch.credential.password" : "password",
-          "ambari.dispatch.recipients" : [
-            "amb...@repo.ambari.apache.org"
-          ],
-          "mail.smtp.tarttls.enable" : "false"
+          "dd": "ddd"
         }
       }
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/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 a6d13b1..27f8303 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
@@ -17,11 +17,16 @@
  */
 
 var App = require('app');
+var validator = require('utils/validator');
 
 App.ManageAlertNotificationsController = Em.Controller.extend({
 
   name: 'manageAlertNotificationsController',
 
+  /**
+   * Are alert notifications loaded
+   * @type {boolean}
+   */
   isLoaded: false,
 
   /**
@@ -65,7 +70,8 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
       label: Em.I18n.t('common.description'),
       value: '',
       defaultValue: ''
-    }
+    },
+    customProperties: Em.A([])
   }),
 
   /**
@@ -80,10 +86,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
    * @type {App.AlertNotification[]}
    */
   alertNotifications: function () {
-    if (this.get('isLoaded')) {
-      return App.AlertNotification.find().toArray();
-    }
-    return [];
+    return this.get('isLoaded') ? App.AlertNotification.find().toArray() : [];
   }.property('isLoaded'),
 
   /**
@@ -93,6 +96,18 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
   selectedAlertNotification: null,
 
   /**
+   * Addable to <code>selectedAlertNotification.properties</code> custom 
property
+   * @type {{name: string, value: string}}
+   */
+  newCustomProperty: {name: '', value: ''},
+
+  /**
+   * List custom property names that shouldn't be displayed on Edit page
+   * @type {string[]}
+   */
+  ignoredCustomProperties: ['ambari.dispatch.recipients'],
+
+  /**
    * Load all Alert Notifications from server
    * Don't do anything if controller not isLoaded
    * @returns {$.ajax|null}
@@ -127,6 +142,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Add Notification button handler
+   * @method addAlertNotification
    */
   addAlertNotification: function () {
     var inputFields = this.get('inputFields');
@@ -138,6 +154,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Edit Notification button handler
+   * @method editAlertNotification
    */
   editAlertNotification: function () {
     this.fillEditCreateInputs();
@@ -147,6 +164,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
   /**
    * Fill inputs of Create/Edit popup form
    * @param addCopyToName define whether add 'Copy of ' to name
+   * @method fillEditCreateInputs
    */
   fillEditCreateInputs: function (addCopyToName) {
     var inputFields = this.get('inputFields');
@@ -162,12 +180,24 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
     ]);
     inputFields.set('description.value', 
selectedAlertNotification.get('description'));
     inputFields.set('method.value', selectedAlertNotification.get('type'));
+    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;
+      inputFields.get('customProperties').pushObject({
+        name: k,
+        value: properties[k],
+        defaultValue: properties[k]
+      });
+    });
   },
 
   /**
    * Show Edit or Create Notification popup
-   * @param isEdit
+   * @param {boolean} isEdit true - edit, false - create
    * @returns {App.ModalPopup}
+   * @method showCreateEditPopup
    */
   showCreateEditPopup: function (isEdit) {
     var self = this;
@@ -198,31 +228,35 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
   /**
    * Create API-formatted object from data populate by user
    * @returns {Object}
+   * @method formatNotificationAPIObject
    */
   formatNotificationAPIObject: function () {
     var inputFields = this.get('inputFields');
     var alertStates = [];
     var properties = {};
-    if (inputFields.severityFilter.value[0]) {
+    if (inputFields.get('severityFilter.value')[0]) {
       alertStates.push('OK');
     }
-    if (inputFields.severityFilter.value[1]) {
+    if (inputFields.get('severityFilter.value')[1]) {
       alertStates.push('WARNING');
     }
-    if (inputFields.severityFilter.value[2]) {
+    if (inputFields.get('severityFilter.value')[2]) {
       alertStates.push('CRITICAL');
     }
-    if (inputFields.severityFilter.value[3]) {
+    if (inputFields.get('severityFilter.value')[3]) {
       alertStates.push('UNKNOWN');
     }
-    if (inputFields.method.value === 'EMAIL') {
-      properties['ambari.dispatch.recipients'] = 
inputFields.email.value.replace(/\s/g, '').split(',');
+    if (inputFields.get('method.value') === 'EMAIL') {
+      properties['ambari.dispatch.recipients'] = 
inputFields.get('email.value').replace(/\s/g, '').split(',');
     }
+    inputFields.get('customProperties').forEach(function (customProperty) {
+      properties[customProperty.name] = customProperty.value;
+    });
     return {
       AlertTarget: {
-        name: inputFields.name.value,
-        description: inputFields.description.value,
-        notification_type: inputFields.method.value,
+        name: inputFields.get('name.value'),
+        description: inputFields.get('description.value'),
+        notification_type: inputFields.get('method.value'),
         alert_states: alertStates,
         properties: properties
       }
@@ -231,8 +265,9 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Send request to server to create Alert Notification
-   * @param apiObject
+   * @param {object} apiObject (@see formatNotificationAPIObject)
    * @returns {$.ajax}
+   * @method createAlertNotification
    */
   createAlertNotification: function (apiObject) {
     return App.ajax.send({
@@ -247,6 +282,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Success callback for <code>createAlertNotification</code>
+   * @method createAlertNotificationSuccessCallback
    */
   createAlertNotificationSuccessCallback: function () {
     this.loadAlertNotifications();
@@ -258,8 +294,9 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Send request to server to update Alert Notification
-   * @param apiObject
+   * @param {object} apiObject (@see formatNotificationAPIObject)
    * @returns {$.ajax}
+   * @method updateAlertNotification
    */
   updateAlertNotification: function (apiObject) {
     return App.ajax.send({
@@ -275,6 +312,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Success callback for <code>updateAlertNotification</code>
+   * @method updateAlertNotificationSuccessCallback
    */
   updateAlertNotificationSuccessCallback: function () {
     this.loadAlertNotifications();
@@ -286,6 +324,8 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Delete Notification button handler
+   * @return {App.ModalPopup}
+   * @method deleteAlertNotification
    */
   deleteAlertNotification: function () {
     var self = this;
@@ -303,6 +343,7 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Success callback for <code>deleteAlertNotification</code>
+   * @method deleteAlertNotificationSuccessCallback
    */
   deleteAlertNotificationSuccessCallback: function () {
     this.loadAlertNotifications();
@@ -313,10 +354,98 @@ App.ManageAlertNotificationsController = 
Em.Controller.extend({
 
   /**
    * Duplicate Notification button handler
+   * @method duplicateAlertNotification
    */
   duplicateAlertNotification: function () {
     this.fillEditCreateInputs(true);
     this.showCreateEditPopup();
+  },
+
+  /**
+   * Show popup with form for new custom property
+   * @method addCustomPropertyHandler
+   * @return {App.ModalPopup}
+   */
+  addCustomPropertyHandler: function () {
+    var self = this;
+
+    return App.ModalPopup.show({
+
+      header: Em.I18n.t('alerts.notifications.addCustomPropertyPopup.header'),
+
+      primary: Em.I18n.t('common.add'),
+
+      bodyClass: Em.View.extend({
+
+        /**
+         * If some error with new custom property
+         * @type {boolean}
+         */
+        isError: false,
+
+        controller: this,
+
+        /**
+         * Error message for new custom property (invalid name, existed name 
etc)
+         * @type {string}
+         */
+        errorMessage: '',
+
+        /**
+         * Check new custom property for errors with its name
+         * @method errorHandler
+         */
+        errorsHandler: function () {
+          var name = this.get('controller.newCustomProperty.name');
+          var flag = validator.isValidConfigKey(name);
+          if (flag) {
+            if 
(this.get('controller.inputFields.customProperties').mapProperty('name').contains(name)
 ||
+              this.get('controller.ignoredCustomProperties').contains(name)) {
+              this.set('errorMessage', 
Em.I18n.t('alerts.notifications.addCustomPropertyPopup.error.propertyExists'));
+              flag = false;
+            }
+          }
+          else {
+            this.set('errorMessage', 
Em.I18n.t('alerts.notifications.addCustomPropertyPopup.error.invalidPropertyName'));
+          }
+          this.set('isError', !flag);
+          this.set('parentView.disablePrimary', !flag);
+        }.observes('controller.newCustomProperty.name'),
+
+        templateName: 
require('templates/main/alerts/add_custom_config_to_alert_notification_popup')
+      }),
+
+      onPrimary: function () {
+        self.addCustomProperty();
+        self.set('newCustomProperty', {name: '', value: ''}); // cleanup
+        this.hide();
+      }
+
+    });
+  },
+
+  /**
+   * Add Custom Property to <code>selectedAlertNotification</code> (push it to 
<code>properties</code>-field)
+   * @method addCustomProperty
+   */
+  addCustomProperty: function () {
+    var newCustomProperty = this.get('newCustomProperty');
+    this.get('inputFields.customProperties').pushObject({
+      name: newCustomProperty.name,
+      value: newCustomProperty.value,
+      defaultValue: newCustomProperty.value
+    });
+  },
+
+  /**
+   * "Remove"-button click handler
+   * Delete customProperty from <code>inputFields.customProperties</code>
+   * @param {object} e
+   * @method removeCustomProperty
+   */
+  removeCustomPropertyHandler: function (e) {
+    var customProperties = this.get('inputFields.customProperties');
+    this.set('inputFields.customProperties', 
customProperties.without(e.context));
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index e148eb6..40b8d14 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -878,6 +878,10 @@ Em.I18n.translations = {
   'alerts.definition.details.notification': 'Notification',
   'alerts.definition.details.noAlerts': 'No alert instances to show',
 
+  'alerts.notifications.addCustomPropertyPopup.header': 'Add Custom Property',
+  'alerts.notifications.addCustomPropertyPopup.error.propertyExists': 'Custom 
Property with current name already exists',
+  'alerts.notifications.addCustomPropertyPopup.error.invalidPropertyName': 
'Custom Property name is invalid',
+
 
   'wizard.progressPage.notice.completed':'Please proceed to the next step.',
   'wizard.progressPage.notice.failed':'You can click on the Retry button to 
retry failed tasks.',

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/styles/alerts.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/alerts.less 
b/ambari-web/app/styles/alerts.less
index df07714..fdb2cf8 100644
--- a/ambari-web/app/styles/alerts.less
+++ b/ambari-web/app/styles/alerts.less
@@ -324,6 +324,11 @@
       width: inherit;
     }
   }
+
+  .icon-minus-sign {
+    color: #FF4B4B;
+  }
+
 }
 
 /*****start styles for manage alerts popup*****/

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/templates/main/alerts/add_custom_config_to_alert_notification_popup.hbs
----------------------------------------------------------------------
diff --git 
a/ambari-web/app/templates/main/alerts/add_custom_config_to_alert_notification_popup.hbs
 
b/ambari-web/app/templates/main/alerts/add_custom_config_to_alert_notification_popup.hbs
new file mode 100644
index 0000000..8f86d5e
--- /dev/null
+++ 
b/ambari-web/app/templates/main/alerts/add_custom_config_to_alert_notification_popup.hbs
@@ -0,0 +1,42 @@
+{{!
+* 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.
+}}
+
+<form class="form-horizontal alert-configs">
+  <div {{bindAttr class="view.isError:error :control-group"}}>
+    <label class="control-label">{{t common.name}}: </label>
+
+    <div class="controls">
+      {{view Em.TextField valueBinding="controller.newCustomProperty.name"}}
+    </div>
+  </div>
+
+  <div class="control-group">
+    <label class="control-label">{{t common.value}}: </label>
+
+    <div class="controls">
+      {{view Em.TextField valueBinding="controller.newCustomProperty.value"}}
+    </div>
+  </div>
+
+  {{#if view.isError}}
+    <div class="alert alert-danger">
+      {{view.errorMessage}}
+    </div>
+  {{/if}}
+
+</form>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/templates/main/alerts/create_alert_notification.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts/create_alert_notification.hbs 
b/ambari-web/app/templates/main/alerts/create_alert_notification.hbs
index 37ac7a9..9002809 100644
--- a/ambari-web/app/templates/main/alerts/create_alert_notification.hbs
+++ b/ambari-web/app/templates/main/alerts/create_alert_notification.hbs
@@ -70,5 +70,18 @@
       </div>
     </div>
 
+    {{#each customProperty in controller.inputFields.customProperties}}
+      <div class="control-group">
+        <label class="control-label" 
for="inputGroups">{{customProperty.name}}</label>
+
+        <div class="controls">
+          {{view Em.TextField valueBinding="customProperty.value" 
class="input-xlarge"}}
+          <a href="#" {{action "removeCustomPropertyHandler" customProperty 
target="controller"}} class="btn btn-small"><span 
class="icon-minus-sign"></span></a>
+        </div>
+      </div>
+    {{/each}}
+
+    <a href="#" {{action addCustomPropertyHandler target="controller"}}>{{t 
installer.step7.config.addProperty}} ...</a>
+
   </form>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/utils/ajax/ajax.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/ajax/ajax.js 
b/ambari-web/app/utils/ajax/ajax.js
index 662c9b8..0956f1c 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -363,7 +363,7 @@ var urls = {
   },
   'alerts.notifications': {
     'real': '/alert_targets?fields=*',
-    'mock': ''
+    'mock': '/data/alerts/alertNotifications.json'
   },
   'alerts.instances.by_definition': {
     'real': 
'/clusters/{clusterName}/alerts?fields=*&(Alert/definition_id={definitionId}|Alert/state.in(CRITICAL,WARNING))',
@@ -2021,7 +2021,7 @@ var urls = {
         action: 'check_host',
         parameters: { }
       };
-      $.extend(true, requestInfo, data.requestInfo)
+      $.extend(true, requestInfo, data.requestInfo);
       return {
         type: 'POST',
         data: JSON.stringify({

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/ambari-web/app/utils/validator.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/validator.js 
b/ambari-web/app/utils/validator.js
index d1af967..3e84982 100644
--- a/ambari-web/app/utils/validator.js
+++ b/ambari-web/app/utils/validator.js
@@ -187,22 +187,22 @@ module.exports = {
    * Try to prevent invalid regexp.
    * For example: 
/api/v1/clusters/c1/hosts?Hosts/host_name.matches(.*localhost.)
    *
-   * @params {String} value - string to validate
+   * @param {String} value - string to validate
    * @return {Boolean}
    * @method isValidMatchesRegexp
    */
   isValidMatchesRegexp: function(value) {
     var checkPair = function(chars) {
-      chars = chars.map(function(char) { return '\\' + char; });
+      chars = chars.map(function(c) { return '\\' + c; });
       var charsReg = new RegExp(chars.join('|'), 'g');
       if (charsReg.test(value)) {
         var pairContentReg = new RegExp(chars.join('.*'), 'g');
         if (!pairContentReg.test(value)) return false;
-        var pairCounts = chars.map(function(char) { return value.match(new 
RegExp(char, 'g')).length; });
+        var pairCounts = chars.map(function(c) { return value.match(new 
RegExp(c, 'g')).length; });
         if (pairCounts[0] != pairCounts[1] ) return false;
       }
       return true;
-    }
+    };
     if (/^[\?\|\*\!,]/.test(value)) return false;
     return /^((\.\*?)?([\w\[\]\?\-_,\|\*\!\{\}]*)?)+(\.\*?)?$/g.test(value) && 
(checkPair(['[',']'])) && (checkPair(['{','}']));
   },

http://git-wip-us.apache.org/repos/asf/ambari/blob/1b6002a5/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 15f9ede..2ae6c6e 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
@@ -18,6 +18,8 @@
 
 var App = require('app');
 var controller;
+var helpers = require('test/helpers');
+
 describe('App.ManageAlertNotificationsController', function () {
 
   beforeEach(function () {
@@ -162,7 +164,7 @@ describe('App.ManageAlertNotificationsController', function 
() {
 
   describe('#fillEditCreateInputs()', function () {
 
-    it("should map properties from selectedAlertNotification to inputFields", 
function () {
+    it("should map properties from selectedAlertNotification to inputFields 
(ambari.dispatch.recipients ignored)", function () {
 
       controller.set('selectedAlertNotification', Em.Object.create({
         name: 'test_name',
@@ -173,7 +175,8 @@ describe('App.ManageAlertNotificationsController', function 
() {
           'ambari.dispatch.recipients': [
             'te...@test.test',
             'te...@test.test'
-          ]
+          ],
+          'customName': 'customValue'
         }
       }));
 
@@ -195,7 +198,11 @@ describe('App.ManageAlertNotificationsController', 
function () {
         },
         description: {
           value: ''
-        }
+        },
+        customProperties: [
+          {name: 'customName', value: 'customValue1', defaultValue: 
'customValue1'},
+          {name: 'customName2', value: 'customValue1', defaultValue: 
'customValue1'}
+        ]
       }));
 
       controller.fillEditCreateInputs();
@@ -218,7 +225,10 @@ describe('App.ManageAlertNotificationsController', 
function () {
         },
         description: {
           value: 'test_description'
-        }
+        },
+        customProperties: [
+          {name: 'customName', value: 'customValue', defaultValue: 
'customValue'}
+        ]
       }));
 
     });
@@ -271,7 +281,11 @@ describe('App.ManageAlertNotificationsController', 
function () {
         },
         description: {
           value: 'test_description'
-        }
+        },
+        customProperties: [
+          {name: 'n1', value: 'v1'},
+          {name: 'n2', value: 'v2'}
+        ]
       }));
 
       var result = controller.formatNotificationAPIObject();
@@ -288,7 +302,9 @@ describe('App.ManageAlertNotificationsController', function 
() {
               'te...@test.test',
               'te...@test.test',
               'te...@test.test'
-            ]
+            ],
+            'n1': 'v1',
+            'n2': 'v2'
           }
         }
       });
@@ -387,7 +403,6 @@ describe('App.ManageAlertNotificationsController', function 
() {
 
   });
 
-
   describe('#deleteAlertNotificationSuccessCallback()', function () {
 
     it("should call loadAlertNotifications, 
selectedAlertNotification.deleteRecord and set null to 
selectedAlertNotification", function () {
@@ -433,5 +448,104 @@ describe('App.ManageAlertNotificationsController', 
function () {
 
   });
 
+  describe('#addCustomProperty', function () {
+
+    beforeEach(function () {
+      controller.set('inputFields.customProperties', []);
+    });
+
+    it('should add custom Property to customProperties', function () {
+
+      controller.set('newCustomProperty', {name: 'n1', value: 'v1'});
+      controller.addCustomProperty();
+      helpers.nestedExpect([{name: 'n1', value: 'v1', defaultValue: 'v1'}], 
controller.get('inputFields.customProperties'));
+
+    });
+
+  });
+
+  describe('#removeCustomPropertyHandler', function () {
+
+    var c = {name: 'n2', value: 'v2', defaultValue: 'v2'};
+
+    beforeEach(function () {
+      controller.set('inputFields.customProperties', [
+        {name: 'n1', value: 'v1', defaultValue: 'v1'},
+        c,
+        {name: 'n3', value: 'v3', defaultValue: 'v3'}
+      ]);
+    });
+
+    it('should remove selected custom property', function () {
+
+      controller.removeCustomPropertyHandler({context: c});
+      helpers.nestedExpect(
+        [
+          {name: 'n1', value: 'v1', defaultValue: 'v1'},
+          {name: 'n3', value: 'v3', defaultValue: 'v3'}
+        ],
+        controller.get('inputFields.customProperties')
+      );
+
+    });
+
+  });
+
+  describe('#addCustomPropertyHandler', function () {
+
+    it('should clean up newCustomProperty on primary click', function () {
+
+      controller.set('newCustomProperty', {name: 'n1', value: 'v1'});
+      controller.addCustomPropertyHandler().onPrimary();
+      expect(controller.get('newCustomProperty')).to.eql({name: '', value: 
''});
+
+    });
+
+    describe('#bodyClass', function () {
+
+      var view;
+
+      beforeEach(function () {
+        view = controller.addCustomPropertyHandler().get('bodyClass').create({
+          parentView: Em.View.create(),
+          controller: Em.Object.create({
+            inputFields: Em.Object.create({
+              customProperties: [
+                {name: 'n1', value: 'v1', defaultValue: 'v1'}
+              ]
+            }),
+            newCustomProperty: {name: '', value: ''}
+          })
+        });
+      });
+
+      describe('#errorHandler', function () {
+
+        it('should fire invalid name', function () {
+
+          view.set('controller.newCustomProperty.name', '!!');
+          view.errorsHandler();
+          expect(view.get('isError')).to.be.true;
+          expect(view.get('parentView.disablePrimary')).to.be.true;
+          expect(view.get('errorMessage.length') > 0).to.be.true;
+
+        });
+
+        it('should fire existing property name', function () {
+
+          view.set('controller.newCustomProperty.name', 'n1');
+          view.errorsHandler();
+          expect(view.get('isError')).to.be.true;
+          expect(view.get('parentView.disablePrimary')).to.be.true;
+          expect(view.get('errorMessage.length') > 0).to.be.true;
+
+        });
+
+      });
+
+    });
+
+  });
+
 });
 

Reply via email to