Repository: ambari
Updated Branches:
  refs/heads/trunk 6a837985f -> 0661a4b39


AMBARI-5442. Tests coverage for helper.js and component.js. (Buzhor Denys via 
alexantonenko)


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

Branch: refs/heads/trunk
Commit: 0661a4b398d941d6ad78aac8b871d6cd01882562
Parents: 6a83798
Author: Alex Antonenko <hiv...@gmail.com>
Authored: Fri Apr 11 16:57:11 2014 +0300
Committer: Alex Antonenko <hiv...@gmail.com>
Committed: Fri Apr 11 16:57:11 2014 +0300

----------------------------------------------------------------------
 ambari-web/app/app.js                           |   8 +-
 ambari-web/app/assets/test/tests.js             |   2 +
 ambari-web/app/utils/component.js               |   7 +-
 ambari-web/app/utils/helper.js                  | 173 +++++++++++----
 ambari-web/karma.conf.js                        |   1 +
 ambari-web/test/app_test.js                     |   9 +
 .../global/cluster_controller_test.js           |   4 +-
 ambari-web/test/init_model_test.js              |  29 ++-
 ambari-web/test/installer/step9_test.js         |   8 +-
 ambari-web/test/utils/component_test.js         | 121 +++++++++++
 ambari-web/test/utils/helper_test.js            | 209 +++++++++++++++++++
 ambari-web/test/views/main/host/summary_test.js |  15 +-
 12 files changed, 528 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/app/app.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/app.js b/ambari-web/app/app.js
index 7234c55..b802a99 100644
--- a/ambari-web/app/app.js
+++ b/ambari-web/app/app.js
@@ -89,14 +89,12 @@ module.exports = Em.Application.create({
   /**
    * List of disabled components for the current stack with related info.
    * Each element has followed structure:
-   * @type {Em.Object}
+   * @type {Em.Enumerable.<Em.Object>}
    *   @property componentName {String} - name of the component
    *   @property properties {Object} - mapped properties by site files,
    *    for example:
    *      properties: { global_properties: [], site_properties: [], etc. }
    *   @property reviewConfigs {Ember.Object} - reference review_configs.js
-   *
-   * @type {Array}
    */
   stackDependedComponents: [],
 
@@ -191,6 +189,8 @@ module.exports = Em.Application.create({
    * otherwise enable component and remove it from stackDependedComponents
    * Check forbidden/allowed components and
    * remove/restore related data.
+   *
+   * @method handleStackDependedComponents
    */
   handleStackDependedComponents: function () {
     // need for unit testing and test mode
@@ -256,4 +256,4 @@ module.exports = Em.Application.create({
       clients: 
self.StackServiceComponent.find().filterProperty('isClient',true).mapProperty('componentName')
     })
   }.property()
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/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 40f1e25..efa51d3 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -86,6 +86,8 @@ require('test/utils/validator_test');
 require('test/utils/config_test');
 require('test/utils/string_utils_test');
 require('test/utils/lazy_loading_test');
+require('test/utils/helper_test');
+require('test/utils/component_test');
 require('test/views/common/chart/linear_time_test');
 require('test/views/common/filter_view_test');
 require('test/views/common/table_view_test');

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/app/utils/component.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/component.js 
b/ambari-web/app/utils/component.js
index e085763..e7e8540 100644
--- a/ambari-web/app/utils/component.js
+++ b/ambari-web/app/utils/component.js
@@ -35,6 +35,8 @@ module.exports = {
    *    isClient : false
    * }]
    *
+   *  @method getInstalledComponents
+   *  @return {object[]}
    */
   getInstalledComponents : function(){
     var components = App.HostComponent.find();
@@ -57,8 +59,11 @@ module.exports = {
   },
 
   /**
+   * Format and load info about components to StackServiceComponent model.
    *
-   * @param data
+   * @method loadStackServiceComponentModel
+   * @param data {object} response from server
+   * @return {object} formatted info about components
    */
   loadStackServiceComponentModel: function(data) {
     var serviceComponents = {items: []};

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/app/utils/helper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/helper.js b/ambari-web/app/utils/helper.js
index 26ec0f1..d8543cb 100644
--- a/ambari-web/app/utils/helper.js
+++ b/ambari-web/app/utils/helper.js
@@ -16,22 +16,52 @@
  * limitations under the License.
  */
 
+/**
+ * Remove spaces at beginning and ending of line.
+ * @example
+ *  var str = "  I'm a string  "
+ *  str.trim() // return "I'm a string"
+ * @method trim
+ * @return {string}
+ */
 String.prototype.trim = function () {
   return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
 };
-
+/**
+ * Determines whether string end within another string.
+ *
+ * @method endsWith
+ * @param suffix {string}  substring for search
+ * @return {boolean}
+ */
 String.prototype.endsWith = function(suffix) {
   return this.indexOf(suffix, this.length - suffix.length) !== -1;
 };
-
+/**
+ * Determines whether string start within another string.
+ *
+ * @method startsWith
+ * @param prefix {string} substring for search
+ * @return {boolean}
+ */
 String.prototype.startsWith = function (prefix){
   return this.indexOf(prefix) == 0;
 };
-
+/**
+ * Determines whether string founded within another string.
+ *
+ * @method contains
+ * @param substring {string} substring for search
+ * @return {boolean}
+ */
 String.prototype.contains = function(substring) {
   return this.indexOf(substring) != -1;
 };
-
+/**
+ * Capitalize the first letter of string.
+ * @method capitalize
+ * @return {string}
+ */
 String.prototype.capitalize = function () {
   return this.charAt(0).toUpperCase() + this.slice(1);
 };
@@ -49,9 +79,10 @@ String.prototype.capitalize = function () {
  *  tofind.findIn(person, 1); // 'yes'
  *  tofind.findIn(person, 2); // null
  *
- *  @param multi  Object
- *  @param index  Occurrence count of this key
- *  @return Value of key at given index
+ *  @method findIn
+ *  @param multi {object}
+ *  @param index {number} Occurrence count of this key
+ *  @return {*} Value of key at given index
  */
 String.prototype.findIn = function(multi, index, _foundValues) {
   if (!index) {
@@ -82,10 +113,14 @@ String.prototype.findIn = function(multi, index, 
_foundValues) {
   }
   return value;
 };
-
 /**
- * Replace {i} with argument. where i is number of argument to replace with
- * @return {String}
+ * Replace {i} with argument. where i is number of argument to replace with.
+ * @example
+ *  var str = "{0} world{1}";
+ *  str.format("Hello", "!") // return "Hello world!"
+ *
+ * @method format
+ * @return {string}
  */
 String.prototype.format = function () {
   var args = arguments;
@@ -93,7 +128,14 @@ String.prototype.format = function () {
     return typeof args[number] != 'undefined' ? args[number] : match;
   });
 };
-
+/**
+ * Wrap words in string within template.
+ *
+ * @method highlight
+ * @param {string[]} words - words to wrap
+ * @param {string} [highlightTemplate="<b>{0}</b>"] - template for wrapping
+ * @return {string}
+ */
 String.prototype.highlight = function (words, highlightTemplate) {
   var self = this;
   highlightTemplate = highlightTemplate ? highlightTemplate : "<b>{0}</b>";
@@ -107,7 +149,20 @@ String.prototype.highlight = function (words, 
highlightTemplate) {
 
   return self;
 };
-
+/**
+ * Convert time in milliseconds to object contained days, hours and minutes.
+ * @typedef ConvertedTime
+ *  @type {Object}
+ *  @property {number} d - days
+ *  @property {number} h - hours
+ *  @property {string} m - minutes
+ * @example
+ *  var time = 1000000000;
+ *  time.toDaysHoursMinutes() // {d: 11, h: 13, m: "46.67"}
+ *
+ * @method toDaysHoursMinutes
+ * @return {object}
+ */
 Number.prototype.toDaysHoursMinutes = function () {
   var formatted = {},
     dateDiff = this,
@@ -125,7 +180,6 @@ Number.prototype.toDaysHoursMinutes = function () {
 
   return formatted;
 };
-
 /**
  Sort an array by the key specified in the argument.
  Handle only native js objects as element of array, not the Ember's object.
@@ -152,13 +206,14 @@ Array.prototype.sortPropertyLight = function (path) {
   });
   return this;
 };
-
+/** @namespace Em **/
 Em.CoreObject.reopen({
   t:function (key, attrs) {
     return Em.I18n.t(key, attrs)
   }
 });
 
+/** @namespace Em.Handlebars **/
 Em.Handlebars.registerHelper('log', function (variable) {
   console.log(variable);
 });
@@ -186,12 +241,19 @@ Em.Handlebars.registerHelper('highlight', function 
(property, words, fn) {
 
   return new Em.Handlebars.SafeString(property);
 });
-
+/**
+ * @namespace App
+ */
 App = require('app');
 
 /**
  * Certain variables can have JSON in string
  * format, or in JSON format itself.
+ *
+ * @memberof App
+ * @function parseJson
+ * @param {string|object}
+ * @return {object}
  */
 App.parseJSON = function (value) {
   if (typeof value == "string") {
@@ -203,8 +265,9 @@ App.parseJSON = function (value) {
  * Check for empty <code>Object</code>, built in Em.isEmpty()
  * doesn't support <code>Object</code> type
  *
- * @params obj {Object}
- *
+ * @memberof App
+ * @method isEmptyObject
+ * @param obj {Object}
  * @return {Boolean}
  */
 App.isEmptyObject = function(obj) {
@@ -212,11 +275,16 @@ App.isEmptyObject = function(obj) {
   for (var prop in obj) { if (obj.hasOwnProperty(prop)) {empty = false; 
break;} }
   return empty;
 }
-
+/**
+ *
+ * @namespace App
+ * @namespace App.format
+ */
 App.format = {
-
   /**
-   * @type Object
+   * @memberof App.format
+   * @type {object}
+   * @property components
    */
   components: {
     'APP_TIMELINE_SERVER': 'App Timeline Server',
@@ -294,7 +362,9 @@ App.format = {
   },
 
   /**
-   * @type Object
+   * @memberof App.format
+   * @property command
+   * @type {object}
    */
   command: {
     'INSTALL': 'Install',
@@ -312,7 +382,11 @@ App.format = {
 
   /**
    * convert role to readable string
-   * @param role
+   *
+   * @memberof App.format
+   * @method role
+   * @param {string} role
+   * return {string}
    */
   role:function (role) {
     return this.components[role] ? this.components[role] : '';
@@ -320,7 +394,11 @@ App.format = {
 
   /**
    * convert command_detail to readable string, show the string for all tasks 
name
-   * @param command_detail
+   *
+   * @memberof App.format
+   * @method commandDetail
+   * @param {string} command_detail
+   * @return {string}
    */
   commandDetail: function (command_detail) {
     var detailArr = command_detail.split(' ');
@@ -350,13 +428,21 @@ App.format = {
   },
 
   /**
-   * PENDING - Not queued yet for a host
-   * QUEUED - Queued for a host
-   * IN_PROGRESS - Host reported it is working
-   * COMPLETED - Host reported success
-   * FAILED - Failed
-   * TIMEDOUT - Host did not respond in time
-   * ABORTED - Operation was abandoned
+   * Convert uppercase status name to downcase.
+   * <br>
+   * <br>PENDING - Not queued yet for a host
+   * <br>QUEUED - Queued for a host
+   * <br>IN_PROGRESS - Host reported it is working
+   * <br>COMPLETED - Host reported success
+   * <br>FAILED - Failed
+   * <br>TIMEDOUT - Host did not respond in time
+   * <br>ABORTED - Operation was abandoned
+   *
+   * @memberof App.format
+   * @method taskStatus
+   * @param {string} _taskStatus
+   * @return {string}
+   *
    */
   taskStatus:function (_taskStatus) {
     return _taskStatus.toLowerCase();
@@ -366,8 +452,11 @@ App.format = {
 /**
  * wrapper to bootstrap popover
  * fix issue when popover stuck on view routing
- * @param self
- * @param options
+ *
+ * @memberof App
+ * @method popover
+ * @param {DOMElement} self
+ * @param {object} options
  */
 App.popover = function(self, options) {
   self.popover(options);
@@ -379,11 +468,14 @@ App.popover = function(self, options) {
 /**
  * wrapper to bootstrap tooltip
  * fix issue when tooltip stuck on view routing
- * @param self - DOM element
- * @param options
+ * @memberof App
+ * @method tooltip
+ * @param {DOMElement} self
+ * @param {object} options
  */
 App.tooltip = function(self, options) {
   self.tooltip(options);
+  /* istanbul ignore next */
   self.on("remove", function () {
     $(this).trigger('mouseleave');
   });
@@ -392,16 +484,21 @@ App.tooltip = function(self, options) {
 /**
  * wrapper to Date().getTime()
  * fix issue when client clock and server clock not sync
- * @return timeStamp of current server clock
+ *
+ * @memberof App
+ * @method dateTime
+ * @return {Number} timeStamp of current server clock
  */
 App.dateTime = function() {
   return new Date().getTime() + App.clockDistance;
 };
 
-/*
+/**
  * Helper function for bound property helper registration
- * @params name {String} - name of helper
- * @params view {Em.View} - view
+ * @memberof App
+ * @method registerBoundHelper
+ * @param name {String} name of helper
+ * @param view {Em.View} view
  */
 App.registerBoundHelper = function(name, view) {
   Em.Handlebars.registerHelper(name, function(property, options) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/karma.conf.js
----------------------------------------------------------------------
diff --git a/ambari-web/karma.conf.js b/ambari-web/karma.conf.js
index 9d841dd..3a54978 100644
--- a/ambari-web/karma.conf.js
+++ b/ambari-web/karma.conf.js
@@ -150,6 +150,7 @@ module.exports = function(config) {
     // If browser does not capture in given timeout [ms], kill it
     captureTimeout: 60000,
 
+    browserNoActivityTimeout: 30000,
 
     // Continuous Integration mode
     // if true, it capture browsers, run tests and exit

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/app_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/app_test.js b/ambari-web/test/app_test.js
index d82ab3c..e24ff9a 100644
--- a/ambari-web/test/app_test.js
+++ b/ambari-web/test/app_test.js
@@ -20,6 +20,7 @@ var App = require('app');
 require('views/common/quick_view_link_view');
 require('models/host_component');
 require('models/stack_service_component');
+var modelSetup = require('test/init_model_test');
 
 describe('#App', function() {
 
@@ -363,6 +364,14 @@ describe('#App', function() {
 
   describe('#handleStackDependedComponents()', function () {
 
+    beforeEach(function(){
+      modelSetup.setupStackServiceComponent();
+    });
+
+    afterEach(function(){
+      modelSetup.cleanStackServiceComponent();
+    });
+
     it('if handleStackDependencyTest is true then stackDependedComponents 
should be unmodified', function () {
       App.set('testMode', false);
       App.set('handleStackDependencyTest', true);

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/controllers/global/cluster_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/global/cluster_controller_test.js 
b/ambari-web/test/controllers/global/cluster_controller_test.js
index 9b099f9..c1461b7 100644
--- a/ambari-web/test/controllers/global/cluster_controller_test.js
+++ b/ambari-web/test/controllers/global/cluster_controller_test.js
@@ -232,7 +232,7 @@ describe('App.clusterController', function () {
     it('singleNodeInstall = true', function () {
       App.set('singleNodeInstall', true);
       controller.set('gangliaWebProtocol', '');
-      expect(controller.get('gangliaUrl')).to.equal("http://:42080/ganglia";);
+      expect(controller.get('gangliaUrl')).to.equal("http://"; + 
location.hostname + ":42080/ganglia");
     });
     it('singleNodeAlias is "alias"', function () {
       App.set('singleNodeAlias', 'alias');
@@ -449,4 +449,4 @@ describe('App.clusterController', function () {
     });
   });
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/init_model_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/init_model_test.js 
b/ambari-web/test/init_model_test.js
index e94753f..8fbfe6e 100644
--- a/ambari-web/test/init_model_test.js
+++ b/ambari-web/test/init_model_test.js
@@ -21,14 +21,21 @@ require('models/stack_service_component');
 require('mappers/server_data_mapper');
 require('mappers/stack_service_component_mapper');
 
-/**
- * initialization of App.StackServiceComponent model
- * @type {*}
- */
-var data = {items: Em.A([])};
-require('test/service_components').items.forEach(function(i) {
-  i.serviceComponents.forEach(function(sc) {
-    data.items.pushObject(sc.StackServiceComponents);
-  });
-});
-App.stackServiceComponentMapper.map(data);
+module.exports = {
+  setupStackServiceComponent: function() {
+    /**
+     * initialization of App.StackServiceComponent model
+     * @type {*}
+     */
+    var data = {items: Em.A([])};
+    require('test/service_components').items.forEach(function(i) {
+      i.serviceComponents.forEach(function(sc) {
+        data.items.pushObject(sc.StackServiceComponents);
+      });
+    });
+    App.stackServiceComponentMapper.map(data);
+  },
+  cleanStackServiceComponent: function(){
+    App.StackServiceComponent.find().set('content',[]);
+  }
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/installer/step9_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/installer/step9_test.js 
b/ambari-web/test/installer/step9_test.js
index 3eedfe7..e17b309 100644
--- a/ambari-web/test/installer/step9_test.js
+++ b/ambari-web/test/installer/step9_test.js
@@ -23,9 +23,15 @@ require('models/stack_service_component');
 require('models/hosts');
 require('controllers/wizard/step9_controller');
 require('utils/helper');
+var modelSetup = require('test/init_model_test');
 
 describe('App.InstallerStep9Controller', function () {
-
+  beforeEach(function(){
+    modelSetup.setupStackServiceComponent()
+  });
+  afterEach(function(){
+    modelSetup.cleanStackServiceComponent();
+  })
   describe('#isSubmitDisabled', function () {
     var tests = Em.A([
       {controllerName: 'addHostController', state: 'STARTED', e: false},

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/utils/component_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/component_test.js 
b/ambari-web/test/utils/component_test.js
new file mode 100644
index 0000000..4c49cca
--- /dev/null
+++ b/ambari-web/test/utils/component_test.js
@@ -0,0 +1,121 @@
+/**
+ * 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 component = require('utils/component');
+require('models/host_component');
+require('models/stack_service_component');
+
+describe('utils/component', function(){
+  describe('#getInstalledComponents()', function(){
+    beforeEach(function(){
+      App.HostComponent.find().set('content',[]);
+      App.store.loadMany(App.HostComponent, [
+        {
+          "component_name" : "HISTORYSERVER",
+          "is_client" : false,
+          "is_master" : true,
+          "is_slave" : false
+        },
+        {
+          "component_name" : "TASKTRACKER",
+          "is_client" : false,
+          "is_master" : false,
+          "is_slave" : true
+        }
+      ]);
+    });
+    afterEach(function(){
+      App.HostComponent.find().set('content',[]);
+    });
+    it('names of components should be equal for input and output arrays', 
function(){
+      
expect(component.getInstalledComponents().mapProperty('id')).to.have.members(App.HostComponent.find().mapProperty('componentName'));
+    });
+  });
+  describe('#loadStackServiceComponentModel()', function(){
+    var data = {
+      "items": [
+        {
+          "serviceComponents": [
+            {
+              "StackServiceComponents": {
+                "component_category": "CLIENT",
+                "component_name": "FALCON_CLIENT",
+                "is_client": true,
+                "is_master": false,
+                "service_name": "FALCON",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            },
+            {
+              "StackServiceComponents": {
+                "component_category": "MASTER",
+                "component_name": "FALCON_SERVER",
+                "is_client": false,
+                "is_master": true,
+                "service_name": "FALCON",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            }
+          ]
+        },
+        {
+          "serviceComponents": [
+            {
+              "StackServiceComponents": {
+                "component_category": "SLAVE",
+                "component_name": "GANGLIA_MONITOR",
+                "is_client": false,
+                "is_master": false,
+                "service_name": "GANGLIA",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            },
+            {
+              "StackServiceComponents": {
+                "component_category": "MASTER",
+                "component_name": "GANGLIA_SERVER",
+                "is_client": false,
+                "is_master": true,
+                "service_name": "GANGLIA",
+                "stack_name": "HDP",
+                "stack_version": "2.1"
+              }
+            }
+          ]
+        }
+      ]
+    };
+
+    afterEach(function(){
+      App.StackServiceComponent.find().set('content', []);
+    });
+
+    it('should return 4 components', function(){
+      
expect(component.loadStackServiceComponentModel(data).items.length).to.eql(4);
+    });
+
+    it('should load data to StackServiceComponent model', function(){
+      component.loadStackServiceComponentModel(data);
+      expect(App.StackServiceComponent.find().get('content')).have.length(4);
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/utils/helper_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/helper_test.js 
b/ambari-web/test/utils/helper_test.js
new file mode 100644
index 0000000..3718aef
--- /dev/null
+++ b/ambari-web/test/utils/helper_test.js
@@ -0,0 +1,209 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var App = require('app');
+require('utils/helper');
+
+describe('utils/helper', function() {
+  describe('String helpers', function() {
+    describe('#trim()', function(){
+      it('should replace first space', function() {
+        expect(' as d f'.trim()).to.eql('as d f');
+      });
+    });
+    describe('#endsWith()', function() {
+      it('`abcd` ends with `d`', function(){
+        expect('abcd'.endsWith('d')).to.eql(true);
+      });
+      it('`abcd` doesn\'t end with `f`', function(){
+        expect('abcd'.endsWith('f')).to.eql(false);
+      });
+    });
+    describe('#contains()', function() {
+      it('`abc` contains b', function(){
+        expect('abc'.contains('b')).to.eql(true);
+      });
+      it('`abc` doesn\'t contain d', function() {
+        expect('abc'.contains('d')).to.eql(false);
+      });
+    });
+    describe('#capitalize()',function() {
+      it('`abc d` should start with `A`', function() {
+        expect('abc d'.capitalize()).to.eql('Abc d');
+      });
+    });
+    describe('#findIn()', function(){
+      var obj = {
+        a: {
+          a1: 'AVal1'
+        },
+        b: 'BVal',
+        c: {
+          c1: {
+            c2: 'Cval2'
+          },
+          b: 'BVal'
+        }
+      };
+      var testValue = function(key, value) {
+        it('key `' + key + '` should have `' + JSON.stringify(value) + '` 
value', function() {
+          expect(key.findIn(obj)).to.eql(value);
+        });
+      };
+      it('expect return `null` on non-object input', function(){
+        expect('a'.findIn('b')).to.null;
+      });
+      testValue('a', obj.a);
+      testValue('c2', obj.c.c1.c2);
+      testValue('b', obj.b);
+      testValue('d', null);
+    });
+    describe('#format()', function(){
+      it('should replace string correctly', function(){
+        expect("{0} world{1}".format("Hello","!")).to.eql("Hello world!");
+      });
+    });
+    describe('#highlight()', function() {
+      var str = "Hello world! I want to highlight this word!";
+      it('should highlight `word` with default template', function() {
+        var result = str.highlight(['word']);
+        expect(result).to.eql("Hello world! I want to highlight this 
<b>word</b>!");
+      });
+      it('should highlight `world` and `word` with template `<span 
class="yellow">{0}</span>`', function() {
+        var result = str.highlight(["world", "word"], '<span 
class="yellow">{0}</span>');
+        expect(result).to.eql('Hello <span class="yellow">world</span>! I want 
to highlight this <span class="yellow">word</span>!')
+      });
+      var str2 = "First word, second word";
+      it('should highlight `word` multiply times with default template', 
function() {
+        var result = str2.highlight(["word"]);
+        expect(result).to.eql("First <b>word</b>, second <b>word</b>");
+      });
+    });
+  });
+  describe('Number helpers', function(){
+    describe('#toDaysHoursMinutes()', function(){
+      var time = 1000000000;
+      var minute = 1000*60;
+      var hour = 60*minute;
+      var day = 24*hour;
+      var result = time.toDaysHoursMinutes();
+      var testDays = Math.floor(time/day);
+      it('should correct convert days', function(){
+        expect(testDays).to.eql(result.d);
+      });
+      it('should correct convert hours', function(){
+        expect(Math.floor((time - testDays * day)/hour)).to.eql(result.h);
+      });
+      it('should correct convert minutes', function(){
+        expect(((time - Math.floor((time - testDays*day)/hour)*hour - 
testDays*day)/minute).toFixed(2)).to.eql(result.m);
+      });
+    });
+  });
+  describe('Array helpers', function(){
+    describe('#sortPropertyLight()', function(){
+      var testable = [
+        { a: 2 },
+        { a: 1 },
+        { a: 6},
+        { a: 64},
+        { a: 3},
+        { a: 3}
+      ];
+      var result = testable.sortPropertyLight('a');
+      it('should return array with same length', function(){
+        expect(testable.length).to.eql(result.length);
+      });
+      it('should sort array', function() {
+        result.forEach(function(resultObj, index, resultArr) {
+          if (index > resultArr.length - 1)
+            expect(resultObj.a < resultArr[index + 1].a).to.eql(false);
+        });
+      });
+      it('should try to sort without throwing exception', function(){
+        expect(testable.sortPropertyLight(['a'])).to.ok;
+      });
+    });
+  });
+  describe('App helpers', function(){
+    var appendDiv = function() {
+      $('body').append('<div id="tooltip-test"></div>');
+    };
+    var removeDiv = function() {
+      $('body').remove('#tooltip-test');
+    };
+    describe('#isEmptyObject', function(){
+      it('should return true on empty object', function() {
+        expect(App.isEmptyObject({})).to.eql(true);
+      });
+      it('should return false on non-empty object', function() {
+        expect(App.isEmptyObject({ a: 1 })).to.eql(false);
+      });
+    });
+    describe('#parseJSON()', function(){
+      var testable = '{"hello": "world"}';
+      expect(App.parseJSON(testable).hello).to.eql('world');
+    });
+    describe('#tooltip()', function() {
+      beforeEach(appendDiv);
+      afterEach(removeDiv);
+      it('should add tooltip', function() {
+        var tooltip = App.tooltip($('#tooltip-test'));
+        expect($('#tooltip-test').data('tooltip').enabled).to.eql(true);
+      });
+    });
+    describe('#popover()', function() {
+      beforeEach(appendDiv);
+      afterEach(removeDiv);
+      it('should add popover', function() {
+        var tooltip = App.popover($('#tooltip-test'));
+        expect($('#tooltip-test').data('popover').enabled).to.eql(true);
+      });
+    });
+    describe('#App.format', function(){
+      describe('#commandDetail()', function() {
+        var command = "GANGLIA_MONITOR STOP";
+        var ignored = "DECOMMISSION, NAMENODE";
+        var removeString = "SERVICE/HDFS STOP";
+        var nagiosState = "nagios_update_ignore ACTIONEXECUTE";
+        it('should convert command to readable info', function() {
+          expect(App.format.commandDetail(command)).to.eql(' Ganglia Monitor 
Stop');
+        });
+        it('should ignore decommission command', function(){
+          expect(App.format.commandDetail(ignored)).to.eql('  NameNode');
+        });
+        it('should remove SERVICE string from command', function(){
+          expect(App.format.commandDetail(removeString)).to.eql(' HDFS Stop');
+        });
+        it('should return maintenance message', function() {
+          expect(App.format.commandDetail(nagiosState)).to.eql(' Toggle 
Maintenance Mode');
+        });
+      });
+      describe('#taskStatus()', function(){
+        var testable = [
+          { status: 'PENDING', expectable: 'pending'},
+          { status: 'QUEUED', expectable: 'queued'},
+          { status: 'COMPLETED', expectable: 'completed'}
+        ];
+        testable.forEach(function(testObj){
+          it('should convert `' + testObj.status + '` to `' + 
testObj.expectable + '`', function(){
+            
expect(App.format.taskStatus(testObj.status)).to.eql(testObj.expectable);
+          });
+        });
+      });
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/0661a4b3/ambari-web/test/views/main/host/summary_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/host/summary_test.js 
b/ambari-web/test/views/main/host/summary_test.js
index ac6d626..91770b4 100644
--- a/ambari-web/test/views/main/host/summary_test.js
+++ b/ambari-web/test/views/main/host/summary_test.js
@@ -25,6 +25,7 @@ require('views/main/host/summary');
 
 var mainHostSummaryView;
 var extendedMainHostSummaryView = App.MainHostSummaryView.extend({content: {}, 
addToolTip: function(){}, installedServices: []});
+var modelSetup = require('test/init_model_test');
 
 describe('App.MainHostSummaryView', function() {
 
@@ -268,6 +269,13 @@ describe('App.MainHostSummaryView', function() {
 
   describe('#installableClientComponents', function() {
 
+    beforeEach(function(){
+      modelSetup.setupStackServiceComponent();
+    });
+    afterEach(function(){
+      modelSetup.cleanStackServiceComponent();
+    });
+
     it('delete host not supported', function() {
       App.set('supports.deleteHost', false);
       
expect(mainHostSummaryView.get('installableClientComponents')).to.eql([]);
@@ -327,7 +335,12 @@ describe('App.MainHostSummaryView', function() {
   });
 
   describe('#addableComponents', function() {
-
+    beforeEach(function(){
+      modelSetup.setupStackServiceComponent();
+    });
+    afterEach(function(){
+      modelSetup.cleanStackServiceComponent();
+    });
     var tests = Em.A([
       {
         content: Em.Object.create({

Reply via email to