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({