AMBARI-19280 Cover global controllers with unit tests. (atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/98a83c5f Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/98a83c5f Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/98a83c5f Branch: refs/heads/branch-dev-patch-upgrade Commit: 98a83c5f909b5fe5b8debe249496978bd3c6c7d2 Parents: 633ac3b Author: Andrii Tkach <atk...@apache.org> Authored: Thu Dec 22 13:16:46 2016 +0200 Committer: Andrii Tkach <atk...@apache.org> Committed: Thu Dec 22 16:50:55 2016 +0200 ---------------------------------------------------------------------- .../global/background_operations_controller.js | 60 +- .../controllers/global/cluster_controller.js | 179 +++--- .../global/configuration_controller.js | 14 +- .../app/controllers/global/update_controller.js | 5 +- .../global/user_settings_controller.js | 67 ++- .../global/background_operations_test.js | 241 +++++++- .../global/cluster_controller_test.js | 592 +++++++++++++++++++ .../global/configuration_controller_test.js | 163 +++++ .../global/errors_handler_controller_test.js | 10 + .../global/update_controller_test.js | 122 ++++ .../global/user_settings_controller_test.js | 300 ++++++++++ 11 files changed, 1607 insertions(+), 146 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/app/controllers/global/background_operations_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/background_operations_controller.js b/ambari-web/app/controllers/global/background_operations_controller.js index 9612141..3a011f5 100644 --- a/ambari-web/app/controllers/global/background_operations_controller.js +++ b/ambari-web/app/controllers/global/background_operations_controller.js @@ -320,36 +320,46 @@ App.BackgroundOperationsController = Em.Controller.extend({ /** * parse request context and if keyword "_PARSE_" is present then format it - * @param requestContext + * @param {string} requestContext * @return {Object} */ parseRequestContext: function (requestContext) { - var parsedRequestContext; - var service; - var contextCommand; + var context = {}; if (requestContext) { if (requestContext.indexOf(App.BackgroundOperationsController.CommandContexts.PREFIX) !== -1) { - var contextSplits = requestContext.split('.'); - contextCommand = contextSplits[1]; - service = contextSplits[2]; - switch(contextCommand){ - case "STOP": - case "START": - if (service === 'ALL_SERVICES') { - parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(Em.I18n.t('common.allServices')); - } else { - parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(App.format.role(service, true)); - } - break; - case "ROLLING-RESTART": - parsedRequestContext = Em.I18n.t("rollingrestart.rest.context").format(App.format.role(service, true), contextSplits[3], contextSplits[4]); - break; - } + context = this.getRequestContextWithPrefix(requestContext); } else { - parsedRequestContext = requestContext; + context.parsedRequestContext = requestContext; } } else { - parsedRequestContext = Em.I18n.t('requestInfo.unspecified'); + context.parsedRequestContext = Em.I18n.t('requestInfo.unspecified'); + } + return context; + }, + + /** + * + * @param {string} requestContext + * @returns {{requestContext: *, dependentService: *, contextCommand: *}} + */ + getRequestContextWithPrefix: function (requestContext) { + var contextSplits = requestContext.split('.'), + parsedRequestContext, + contextCommand = contextSplits[1], + service = contextSplits[2]; + + switch (contextCommand) { + case "STOP": + case "START": + if (service === 'ALL_SERVICES') { + parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(Em.I18n.t('common.allServices')); + } else { + parsedRequestContext = Em.I18n.t("requestInfo." + contextCommand.toLowerCase()).format(App.format.role(service, true)); + } + break; + case "ROLLING-RESTART": + parsedRequestContext = Em.I18n.t("rollingrestart.rest.context").format(App.format.role(service, true), contextSplits[3], contextSplits[4]); + break; } return { requestContext: parsedRequestContext, @@ -363,13 +373,13 @@ App.BackgroundOperationsController = Em.Controller.extend({ /** * Onclick handler for background operations number located right to logo */ - showPopup: function(){ + showPopup: function () { // load the checkbox on footer first, then show popup. var self = this; App.router.get('userSettingsController').dataLoading('show_bg').done(function (initValue) { App.updater.immediateRun('requestMostRecent'); - if(self.get('popupView') && App.HostPopup.get('isBackgroundOperations')){ - self.set ('popupView.isNotShowBgChecked', !initValue); + if (self.get('popupView') && App.HostPopup.get('isBackgroundOperations')) { + self.set('popupView.isNotShowBgChecked', !initValue); self.set('popupView.isOpen', true); var el = $(self.get('popupView.element')); el.appendTo('#wrapper'); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/app/controllers/global/cluster_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js index d7cedd3..21508ab 100644 --- a/ambari-web/app/controllers/global/cluster_controller.js +++ b/ambari-web/app/controllers/global/cluster_controller.js @@ -164,6 +164,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { error: 'getServerClockErrorCallback' }); }, + getServerClockSuccessCallback: function (data) { var clientClock = new Date().getTime(); var serverClock = (data.RootServiceComponents.server_clock).toString(); @@ -171,8 +172,8 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { App.set('clockDistance', serverClock - clientClock); App.set('currentServerTime', parseInt(serverClock)); }, - getServerClockErrorCallback: function () { - }, + + getServerClockErrorCallback: Em.K, getUrl: function (testUrl, url) { return (App.get('testMode')) ? testUrl : App.get('apiPrefix') + '/clusters/' + App.get('clusterName') + url; @@ -182,10 +183,10 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { * load all data and update load status */ loadClusterData: function () { - var self = this; this.loadAuthorizations(); this.getAllHostNames(); this.loadAmbariProperties(); + if (!App.get('clusterName')) { return; } @@ -196,38 +197,49 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { } App.router.get('userSettingsController').getAllUserSettings(); App.router.get('errorsHandlerController').loadErrorLogs(); - var clusterUrl = this.getUrl('/data/clusters/cluster.json', '?fields=Clusters'); var hostsController = App.router.get('mainHostController'); hostsController.set('isCountersUpdating', true); hostsController.updateStatusCounters(); + this.loadClusterInfo(); + this.restoreUpgradeState(); + App.router.get('wizardWatcherController').getUser(); + + this.loadClusterDataToModel(); + + //force clear filters for hosts page to load all data + App.db.setFilterConditions('mainHostController', null); + + //load cluster-env, used by alert check tolerance + // TODO services auto-start + App.router.get('updateController').updateClusterEnv(); + }, + + loadClusterInfo: function() { + var clusterUrl = this.getUrl('/data/clusters/cluster.json', '?fields=Clusters'); App.HttpClient.get(clusterUrl, App.clusterMapper, { complete: function (jqXHR, textStatus) { App.set('isCredentialStorePersistent', Em.getWithDefault(App.Cluster.find().findProperty('clusterName', App.get('clusterName')), 'isCredentialStorePersistent', false)); } - }, function (jqXHR, textStatus) { - }); - - - self.restoreUpgradeState(); - - App.router.get('wizardWatcherController').getUser(); + }, Em.K); + }, - var updater = App.router.get('updateController'); + /** + * Order of loading: + * 1. load all created service components + * 2. request for service components supported by stack + * 3. load stack components to model + * 4. request for services + * 5. put services in cache + * 6. request for hosts and host-components (single call) + * 7. request for service metrics + * 8. load host-components to model + * 9. load services from cache with metrics to model + */ + loadClusterDataToModel: function() { + var self = this; - /** - * Order of loading: - * 1. load all created service components - * 2. request for service components supported by stack - * 3. load stack components to model - * 4. request for services - * 5. put services in cache - * 6. request for hosts and host-components (single call) - * 7. request for service metrics - * 8. load host-components to model - * 9. load services from cache with metrics to model - */ - self.loadStackServiceComponents(function (data) { + this.loadStackServiceComponents(function (data) { data.items.forEach(function (service) { service.StackServices.is_selected = true; service.StackServices.is_installed = false; @@ -235,64 +247,68 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { App.stackServiceMapper.mapStackServices(data); App.config.setPreDefinedServiceConfigs(true); self.updateLoadStatus('stackComponents'); - updater.updateServices(function () { - self.updateLoadStatus('services'); - - //hosts should be loaded after services in order to properly populate host-component relation in App.cache.services - updater.updateHost(function () { - self.set('isHostsLoaded', true); - console.time('Overall alerts loading time'); - updater.updateAlertGroups(function () { - updater.updateAlertDefinitions(function () { - updater.updateAlertDefinitionSummary(function () { - updater.updateUnhealthyAlertInstances(function () { - console.timeEnd('Overall alerts loading time'); - self.set('isAlertsLoaded', true); - }); - }); - }); - }); - }); - App.config.loadConfigsFromStack(App.Service.find().mapProperty('serviceName')).complete(function () { - App.config.loadClusterConfigsFromStack().complete(function () { - self.set('isConfigsPropertiesLoaded', true); + self.loadServicesAndComponents(); + }); + }, + + loadServicesAndComponents: function() { + var updater = App.router.get('updateController'); + var self = this; + + updater.updateServices(function () { + self.updateLoadStatus('services'); + + //hosts should be loaded after services in order to properly populate host-component relation in App.cache.services + updater.updateHost(function () { + self.set('isHostsLoaded', true); + self.loadAlerts(); + }); + self.loadConfigProperties(); + // components state loading doesn't affect overall progress + updater.updateComponentsState(function () { + self.set('isComponentsStateLoaded', true); + // service metrics should be loaded after components state for mapping service components to service in the DS model + // service metrics loading doesn't affect overall progress + updater.updateServiceMetric(function () { + self.set('isServiceMetricsLoaded', true); + // make second call, because first is light since it doesn't request host-component metrics + updater.updateServiceMetric(function() { + self.set('isHostComponentMetricsLoaded', true); }); - }); - // components state loading doesn't affect overall progress - updater.updateComponentsState(function () { - self.set('isComponentsStateLoaded', true); - // service metrics should be loaded after components state for mapping service components to service in the DS model - // service metrics loading doesn't affect overall progress - updater.updateServiceMetric(function () { - self.set('isServiceMetricsLoaded', true); - // make second call, because first is light since it doesn't request host-component metrics - updater.updateServiceMetric(function() { - self.set('isHostComponentMetricsLoaded', true); - }); - // components config loading doesn't affect overall progress - updater.updateComponentConfig(function () { - self.set('isComponentsConfigLoaded', true); - }); + // components config loading doesn't affect overall progress + updater.updateComponentConfig(function () { + self.set('isComponentsConfigLoaded', true); }); }); }); }); + }, - //force clear filters for hosts page to load all data - App.db.setFilterConditions('mainHostController', null); - - //load cluster-env, used by alert check tolerance // TODO services auto-start - updater.updateClusterEnv(); + loadConfigProperties: function() { + var self = this; - /* Root service mapper maps all the data exposed under Ambari root service which includes ambari configurations i.e ambari-properties - ** This is useful information but its not being used in the code anywhere as of now + App.config.loadConfigsFromStack(App.Service.find().mapProperty('serviceName')).complete(function () { + App.config.loadClusterConfigsFromStack().complete(function () { + self.set('isConfigsPropertiesLoaded', true); + }); + }); + }, - self.loadRootService().done(function (data) { - App.rootServiceMapper.map(data); - self.updateLoadStatus('rootService'); - }); + loadAlerts: function() { + var updater = App.router.get('updateController'); + var self = this; - */ + console.time('Overall alerts loading time'); + updater.updateAlertGroups(function () { + updater.updateAlertDefinitions(function () { + updater.updateAlertDefinitionSummary(function () { + updater.updateUnhealthyAlertInstances(function () { + console.timeEnd('Overall alerts loading time'); + self.set('isAlertsLoaded', true); + }); + }); + }); + }); }, /** @@ -353,7 +369,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { isRunningState: function(status){ if (status) { - return "IN_PROGRESS" == status || "PENDING" == status || status.contains("HOLDING"); + return "IN_PROGRESS" === status || "PENDING" === status || status.contains("HOLDING"); } else { //init state return true; @@ -364,7 +380,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { * ABORTED should be handled as SUSPENDED for the lastUpgradeItem * */ isSuspendedState: function(status){ - return "ABORTED" == status; + return "ABORTED" === status; }, loadRootService: function () { @@ -385,12 +401,13 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { /** * * @param callback + * @returns {?object} */ loadStackServiceComponents: function (callback) { var callbackObj = { loadStackServiceComponentsSuccess: callback }; - App.ajax.send({ + return App.ajax.send({ name: 'wizard.service_components', data: { stackUrl: App.get('stackVersionURL'), @@ -433,9 +450,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { App.router.get('mainController').monitorInactivity(); }, - loadAmbariPropertiesError: function () { - - }, + loadAmbariPropertiesError: Em.K, updateClusterData: function () { var testUrl = '/data/clusters/HDP2/cluster.json'; @@ -463,9 +478,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { App.set("allHostNames", data.items.mapProperty("Hosts.host_name")); }, - getHostNamesError: function () { - - }, + getHostNamesError: Em.K, /** http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/app/controllers/global/configuration_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/configuration_controller.js b/ambari-web/app/controllers/global/configuration_controller.js index 43afc0f..806064a 100644 --- a/ambari-web/app/controllers/global/configuration_controller.js +++ b/ambari-web/app/controllers/global/configuration_controller.js @@ -61,6 +61,12 @@ App.ConfigurationController = Em.Controller.extend({ } return isDifferent; }, + + /** + * + * @param {Array} siteNames + * @returns {*} + */ loadFromDB: function (siteNames) { var dfd = $.Deferred(); var configs = App.db.getConfigs().filter(function (site) { @@ -80,7 +86,7 @@ App.ConfigurationController = Em.Controller.extend({ var dfd = $.Deferred(); if (!tags.everyProperty('tagName')) { var configTags; - var jqXhr = this.loadConfigTags(); + var jqXhr = this.loadConfigTags(); jqXhr.done(function (data) { configTags = data.Clusters.desired_configs; tags.forEach(function (_tag) { @@ -88,10 +94,10 @@ App.ConfigurationController = Em.Controller.extend({ _tag.tagName = configTags[_tag.siteName].tag; } }, self); - self.loadConfigsByTags(tags,dfd); + self.loadConfigsByTags(tags, dfd); }); } else { - self.loadConfigsByTags(tags,dfd); + self.loadConfigsByTags(tags, dfd); } return dfd.promise(); }, @@ -101,7 +107,7 @@ App.ConfigurationController = Em.Controller.extend({ * @params tags * @params dfd jqXhr promise */ - loadConfigsByTags: function (tags,dfd) { + loadConfigsByTags: function (tags, dfd) { var self = this; var loadedConfigs = []; App.config.loadConfigsByTags(tags).done(function (data) { http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/app/controllers/global/update_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/update_controller.js b/ambari-web/app/controllers/global/update_controller.js index ce93b34..a3aee37 100644 --- a/ambari-web/app/controllers/global/update_controller.js +++ b/ambari-web/app/controllers/global/update_controller.js @@ -410,10 +410,10 @@ App.UpdateController = Em.Controller.extend({ params.callback(skipCall, queryParams); } }, - getHostByHostComponentsErrorCallback: function () { + getHostByHostComponentsErrorCallback: Em.K, - }, graphs: [], + graphsUpdate: function (callback) { var existedGraphs = []; this.get('graphs').forEach(function (_graph) { @@ -524,6 +524,7 @@ App.UpdateController = Em.Controller.extend({ complete: callback }); }, + updateComponentConfig: function (callback) { var testUrl = '/data/services/host_component_stale_configs.json'; var componentConfigUrl = this.getUrl(testUrl, '/components?host_components/HostRoles/stale_configs=true&fields=host_components/HostRoles/display_name,host_components/HostRoles/service_name,host_components/HostRoles/state,host_components/HostRoles/maintenance_state,host_components/HostRoles/host_name,host_components/HostRoles/public_host_name,host_components/HostRoles/stale_configs,host_components/HostRoles/desired_admin_state&minimal_response=true'); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/app/controllers/global/user_settings_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/user_settings_controller.js b/ambari-web/app/controllers/global/user_settings_controller.js index 9580400..e971cba 100644 --- a/ambari-web/app/controllers/global/user_settings_controller.js +++ b/ambari-web/app/controllers/global/user_settings_controller.js @@ -169,10 +169,10 @@ App.UserSettingsController = Em.Controller.extend(App.UserPref, { * @returns {*} */ postUserPref: function (key, value) { - var k = key.startsWith('userSettingsKeys.') ? key : 'userSettingsKeys.' + key + '.name'; - var kk = k.replace('userSettingsKeys.', '').replace('.name', ''); - this.set('userSettings.' + kk, value); - return this._super(this.get(k), value); + var normalizedKey = key.startsWith('userSettingsKeys.') ? key : 'userSettingsKeys.' + key + '.name'; + var shortKey = normalizedKey.replace('userSettingsKeys.', '').replace('.name', ''); + this.set('userSettings.' + shortKey, value); + return this._super(this.get(normalizedKey), value); }, /** @@ -187,8 +187,7 @@ App.UserSettingsController = Em.Controller.extend(App.UserPref, { return; } - this.dataLoading() - .done(function(response) { + this.dataLoading().done(function(response) { self.loadPrivileges().complete(function() { self._showSettingsPopup(response); }); @@ -207,27 +206,11 @@ App.UserSettingsController = Em.Controller.extend(App.UserPref, { }, loadPrivilegesSuccessCallback: function(data) { - var key; - var privileges = { - clusters: {}, - views: {} - }; - data.items.forEach(function(privilege) { - privilege = privilege.PrivilegeInfo; - if(privilege.type === 'CLUSTER'){ - // This is cluster - privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || []; - privileges.clusters[privilege.cluster_name].push(privilege.permission_label); - } else if ( privilege.type === 'VIEW'){ - privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || { privileges:[]}; - privileges.views[privilege.instance_name].version = privilege.version; - privileges.views[privilege.instance_name].view_name = privilege.view_name; - privileges.views[privilege.instance_name].privileges.push(privilege.permission_label); - } - }); - // restructure data for view - var clusters = []; - var views = []; + var key, + privileges = this.parsePrivileges(data), + clusters = [], + views = []; + for (key in privileges.clusters) { clusters.push({ name: key, @@ -245,12 +228,38 @@ App.UserSettingsController = Em.Controller.extend(App.UserPref, { privileges.clusters = clusters; privileges.views = views; this.set('privileges', data.items.length ? privileges : null); - this.set('noClusterPriv', $.isEmptyObject(privileges.clusters)); - this.set('noViewPriv', $.isEmptyObject(privileges.views)); + this.set('noClusterPriv', Em.isEmpty(clusters)); + this.set('noViewPriv', Em.isEmpty(views)); this.set('hidePrivileges', this.get('noClusterPriv') && this.get('noViewPriv')); }, /** + * + * @param {?object} data + * @returns {{clusters: {}, views: {}}} + */ + parsePrivileges: function (data) { + var privileges = { + clusters: {}, + views: {} + }; + data.items.forEach(function (privilege) { + privilege = privilege.PrivilegeInfo; + if (privilege.type === 'CLUSTER') { + // This is cluster + privileges.clusters[privilege.cluster_name] = privileges.clusters[privilege.cluster_name] || []; + privileges.clusters[privilege.cluster_name].push(privilege.permission_label); + } else if (privilege.type === 'VIEW') { + privileges.views[privilege.instance_name] = privileges.views[privilege.instance_name] || {privileges: []}; + privileges.views[privilege.instance_name].version = privilege.version; + privileges.views[privilege.instance_name].view_name = privilege.view_name; + privileges.views[privilege.instance_name].privileges.push(privilege.permission_label); + } + }); + return privileges; + }, + + /** * Show popup with settings for user * Don't call this method directly! Use <code>showSettingsPopup</code> * http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/test/controllers/global/background_operations_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/background_operations_test.js b/ambari-web/test/controllers/global/background_operations_test.js index b22c105..323f090 100644 --- a/ambari-web/test/controllers/global/background_operations_test.js +++ b/ambari-web/test/controllers/global/background_operations_test.js @@ -31,9 +31,7 @@ require('utils/host_progress_popup'); describe('App.BackgroundOperationsController', function () { - var controller = App.BackgroundOperationsController.create({ - isInitLoading: Em.K - }); + var controller = App.BackgroundOperationsController.create(); describe('#getQueryParams', function () { /** @@ -713,4 +711,241 @@ describe('App.BackgroundOperationsController', function () { expect(request.get('isRunning')).to.equal(true); }); }); + + describe("#isInitLoading()", function () { + + it("should return false when not on HOSTS_LIST level", function() { + controller.set('levelInfo', Em.Object.create({ + name: 'SERVICES_LIST' + })); + expect(controller.isInitLoading()).to.be.false; + }); + + it("should return false when no request found", function() { + controller.set('levelInfo', Em.Object.create({ + name: 'HOSTS_LIST', + requestId: 1 + })); + controller.set('services', []); + expect(controller.isInitLoading()).to.be.false; + }); + + it("should return false when no request found", function() { + controller.set('levelInfo', Em.Object.create({ + name: 'HOSTS_LIST', + requestId: 1 + })); + controller.set('services', []); + expect(controller.isInitLoading()).to.be.false; + }); + + it("should return false when request has hosts", function() { + controller.set('levelInfo', Em.Object.create({ + name: 'HOSTS_LIST', + requestId: 1 + })); + controller.set('services', [Em.Object.create({ + id: 1, + hostsMap: { + 'host1': {} + } + })]); + expect(controller.isInitLoading()).to.be.false; + }); + + it("should return true when no request has no hosts", function() { + controller.set('levelInfo', Em.Object.create({ + name: 'HOSTS_LIST', + requestId: 1 + })); + controller.set('services', [Em.Object.create({ + id: 1, + hostsMap: {} + })]); + expect(controller.isInitLoading()).to.be.true; + }); + }); + + describe("#callBackFilteredByTask()", function () { + var data = { + Tasks: { + request_id: 1, + host_name: 'host1', + id: 2, + status: 'foo', + stdout: 'bar', + stderr: 'barfoo', + command: 'cmd', + custom_command_name: 'custom-cmd', + structured_out: 'str-out', + output_log: 'out-log', + error_log: 'err-log' + } + }; + + beforeEach(function() { + sinon.stub(App, 'dateTime').returns(1); + }); + + afterEach(function() { + App.dateTime.restore(); + }); + + it("should set task info", function() { + var task = { + Tasks: { + id: 2 + } + }; + controller.set('services', [ + Em.Object.create({ + id: 1, + hostsMap: { + host1: { + logTasks: [task] + } + } + }) + ]); + + controller.callBackFilteredByTask(data); + expect(task).to.be.eql({ + "Tasks": { + "id": 2, + "status": "foo", + "stdout": "bar", + "stderr": "barfoo", + "command": "cmd", + "custom_command_name": "custom-cmd", + "structured_out": "str-out", + "output_log": "out-log", + "error_log": "err-log" + } + }); + expect(controller.get('serviceTimestamp')).to.be.equal(1); + }); + }); + + describe("#parseRequestContext()", function () { + + beforeEach(function() { + sinon.stub(controller, 'getRequestContextWithPrefix').returns({ + parsedRequestContext: 'CTX_WITH_PREFIX' + }); + }); + + afterEach(function() { + controller.getRequestContextWithPrefix.restore(); + }); + + it("no requestContext specified", function() { + expect(controller.parseRequestContext()).to.be.eql({ + parsedRequestContext: Em.I18n.t('requestInfo.unspecified') + }); + }); + + it("requestContext specified", function() { + expect(controller.parseRequestContext('CTX')).to.be.eql({ + parsedRequestContext: 'CTX' + }); + }); + + it("requestContext specified with prefix", function() { + expect(controller.parseRequestContext(App.BackgroundOperationsController.CommandContexts.PREFIX)).to.be.eql({ + parsedRequestContext: 'CTX_WITH_PREFIX' + }); + }); + }); + + describe("#getRequestContextWithPrefix()", function () { + + beforeEach(function() { + sinon.stub(App.format, 'role', function (arg) { + return arg; + }) + }); + + afterEach(function() { + App.format.role.restore(); + }); + + it("custom command", function() { + expect(controller.getRequestContextWithPrefix('prefix.foo.bar')).to.be.eql({ + requestContext: undefined, + dependentService: 'bar', + contextCommand: 'foo' + }); + }); + it("STOP all services command", function() { + expect(controller.getRequestContextWithPrefix('prefix.STOP.ALL_SERVICES')).to.be.eql({ + requestContext: Em.I18n.t("requestInfo.stop").format(Em.I18n.t('common.allServices')), + dependentService: 'ALL_SERVICES', + contextCommand: 'STOP' + }); + }); + it("STOP one service command", function() { + expect(controller.getRequestContextWithPrefix('prefix.STOP.S1')).to.be.eql({ + requestContext: Em.I18n.t("requestInfo.stop").format('S1'), + dependentService: 'S1', + contextCommand: 'STOP' + }); + }); + it("ROLLING-RESTART service command", function() { + expect(controller.getRequestContextWithPrefix('prefix.ROLLING-RESTART.S1.foo.bar')).to.be.eql({ + requestContext: Em.I18n.t("rollingrestart.rest.context").format('S1', 'foo', 'bar'), + dependentService: 'S1', + contextCommand: 'ROLLING-RESTART' + }); + }); + }); + + describe("#showPopup()", function () { + + beforeEach(function() { + sinon.stub(App.router, 'get').returns({ + dataLoading: function() { + return { + done: Em.clb + } + } + }); + sinon.stub(App.HostPopup, 'initPopup').returns(Em.Object.create()); + App.HostPopup.set('isBackgroundOperations', true); + }); + + afterEach(function() { + App.router.get.restore(); + App.HostPopup.initPopup.restore(); + }); + + it("App.updater.immediateRun should be called", function() { + controller.showPopup(); + expect(App.updater.immediateRun.calledWith('requestMostRecent')).to.be.true; + }); + + it("popupView should be created and opened", function() { + controller.set('popupView', null); + controller.showPopup(); + expect(controller.get('popupView')).to.be.eql(Em.Object.create({ + isNotShowBgChecked: true + })); + }); + + it("popupView should be restored and opened", function() { + controller.set('popupView', Em.Object.create()); + controller.showPopup(); + expect(controller.get('popupView')).to.be.eql(Em.Object.create({ + isNotShowBgChecked: true, + isOpen: true + })); + }); + }); + + describe("#clear()", function () { + + it("operationsCount should be 10", function() { + controller.clear(); + expect(controller.get('operationsCount')).to.be.equal(10); + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/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 47708ac..ad6e6f9 100644 --- a/ambari-web/test/controllers/global/cluster_controller_test.js +++ b/ambari-web/test/controllers/global/cluster_controller_test.js @@ -571,4 +571,596 @@ describe('App.clusterController', function () { }); }); + + describe('#loadClientServerClockDistance()', function() { + + beforeEach(function() { + sinon.stub(controller, 'getServerClock').returns({ + done: Em.clb + }); + }); + + afterEach(function() { + controller.getServerClock.restore(); + }); + + it('getServerClock should be called', function() { + expect(controller.loadClientServerClockDistance()).to.be.an.object; + expect(controller.getServerClock).to.be.calledOnce; + }); + }); + + describe('#getServerClock()', function() { + + it('App.ajax.send should be called', function() { + controller.getServerClock(); + var args = testHelpers.findAjaxRequest('name', 'ambari.service'); + expect(args[0]).to.eql({ + name: 'ambari.service', + sender: controller, + data: { + fields: '?fields=RootServiceComponents/server_clock' + }, + success: 'getServerClockSuccessCallback', + error: 'getServerClockErrorCallback' + }); + }); + }); + + describe('#isRunningState()', function() { + var testCases = [ + { + status: '', + expected: true + }, + { + status: 'IN_PROGRESS', + expected: true + }, + { + status: 'PENDING', + expected: true + }, + { + status: 'FAILED_HOLDING', + expected: true + }, + { + status: 'ABORTED', + expected: false + } + ]; + + testCases.forEach(function(test) { + it('status = ' + test.status, function() { + expect(controller.isRunningState(test.status)).to.be.equal(test.expected); + }); + }); + }); + + describe('#isSuspendedState()', function() { + + it('should return true when status is ABORTED', function() { + expect(controller.isSuspendedState('ABORTED')).to.be.true; + }); + }); + + describe('#loadRootService()', function() { + + it('App.ajax.send should be called', function() { + controller.loadRootService(); + var args = testHelpers.findAjaxRequest('name', 'service.ambari'); + expect(args).to.exist; + }); + }); + + describe('#requestHosts()', function() { + + beforeEach(function() { + sinon.stub(App.HttpClient, 'get'); + }); + + afterEach(function() { + App.HttpClient.get.restore(); + }); + + it('App.HttpClient.get should be called', function() { + controller.requestHosts(); + expect(App.HttpClient.get).to.be.calledOnce; + }); + }); + + describe('#loadStackServiceComponents()', function() { + + it('App.ajax.send should be called', function() { + controller.loadStackServiceComponents(); + var args = testHelpers.findAjaxRequest('name', 'wizard.service_components'); + expect(args).to.exist; + }); + }); + + describe('#loadAmbariProperties()', function() { + + it('App.ajax.send should be called', function() { + controller.loadAmbariProperties(); + var args = testHelpers.findAjaxRequest('name', 'ambari.service'); + expect(args).to.exist; + }); + }); + + describe('#loadAuthorizations()', function() { + + it('App.ajax.send should be called', function() { + controller.loadAuthorizations(); + var args = testHelpers.findAjaxRequest('name', 'router.user.authorizations'); + expect(args).to.exist; + }); + }); + + describe('#loadAuthorizationsSuccessCallback()', function() { + var auth = App.get('auth'); + + beforeEach(function() { + sinon.stub(App.db, 'setAuth'); + }); + + afterEach(function() { + App.db.setAuth.restore(); + App.set('auth', auth); + }); + + it('App.db.setAuth should not be called when response is null', function() { + controller.loadAuthorizationsSuccessCallback(null); + expect(App.db.setAuth).to.not.be.called; + }); + + it('App.db.setAuth should not be called when response has no items', function() { + controller.loadAuthorizationsSuccessCallback({items: null}); + expect(App.db.setAuth).to.not.be.called; + }); + + it('App.db.setAuth should be called when response correct', function() { + controller.loadAuthorizationsSuccessCallback({items: [ + { + AuthorizationInfo: { + authorization_id: 'admin' + } + }, + { + AuthorizationInfo: { + authorization_id: 'admin' + } + } + ]}); + expect(App.get('auth')).to.be.eql(['admin']); + expect(App.db.setAuth.calledWith(['admin'])).to.be.true; + }); + }); + + describe('#loadAmbariPropertiesSuccess()', function() { + + beforeEach(function() { + sinon.stub(App.router.get('mainController'), 'monitorInactivity'); + controller.loadAmbariPropertiesSuccess({ + RootServiceComponents: { + properties: { + p1: '1' + } + } + }); + }); + + afterEach(function() { + App.router.get('mainController').monitorInactivity.restore(); + }); + + it('should set ambariProperties', function() { + expect(controller.get('ambariProperties')).to.be.eql({p1: '1'}); + }); + + it('should set isCustomJDK', function() { + expect(controller.get('isCustomJDK')).to.be.true; + }); + + it('monitorInactivity should be called', function() { + expect(App.router.get('mainController').monitorInactivity).to.be.calledOnce; + }); + }); + + describe('#updateClusterData()', function() { + + beforeEach(function() { + sinon.stub(App.HttpClient, 'get'); + }); + + afterEach(function() { + App.HttpClient.get.restore(); + }); + + it('App.HttpClient.get should be called', function() { + controller.updateClusterData(); + expect(App.HttpClient.get).to.be.calledOnce; + }); + }); + + describe('#getAllHostNames()', function() { + + it('App.ajax.send should be called', function() { + controller.getAllHostNames(); + var args = testHelpers.findAjaxRequest('name', 'hosts.all'); + expect(args).to.exist; + }); + }); + + describe('#getHostNamesSuccess()', function() { + + it('should set allHostNames', function() { + controller.getHostNamesSuccess({ + items: [ + { + Hosts: { + host_name: 'host1' + } + } + ] + }); + expect(App.get('allHostNames')).to.be.eql(['host1']); + }); + }); + + describe('#createKerberosAdminSession()', function() { + + beforeEach(function() { + sinon.stub(credentialUtils, 'createOrUpdateCredentials').returns({ + then: Em.clb + }); + }); + + afterEach(function() { + credentialUtils.createOrUpdateCredentials.restore(); + }); + + it('credentialUtils.createOrUpdateCredentials should be called', function() { + controller.createKerberosAdminSession({}, {}); + expect(credentialUtils.createOrUpdateCredentials).to.be.calledOnce; + }); + }); + + describe('#getAllUpgrades()', function() { + + it('App.ajax.send should be called', function() { + controller.getAllUpgrades(); + var args = testHelpers.findAjaxRequest('name', 'cluster.load_last_upgrade'); + expect(args).to.exist; + }); + }); + + describe('#triggerQuickLinksUpdate()', function() { + + it('should increment quickLinksUpdateCounter', function() { + controller.set('quickLinksUpdateCounter', 0); + controller.triggerQuickLinksUpdate(); + expect(controller.get('quickLinksUpdateCounter')).to.be.equal(1); + }); + }); + + describe('#loadClusterData()', function() { + + beforeEach(function() { + sinon.stub(controller, 'loadAuthorizations'); + sinon.stub(controller, 'getAllHostNames'); + sinon.stub(controller, 'loadAmbariProperties'); + sinon.stub(controller, 'loadClusterInfo'); + sinon.stub(controller, 'restoreUpgradeState'); + sinon.stub(controller, 'loadClusterDataToModel'); + sinon.stub(App.router.get('mainController'), 'startPolling'); + sinon.stub(App.router.get('userSettingsController'), 'getAllUserSettings'); + sinon.stub(App.router.get('errorsHandlerController'), 'loadErrorLogs'); + sinon.stub(App.router.get('mainHostController'), 'updateStatusCounters'); + sinon.stub(App.router.get('wizardWatcherController'), 'getUser'); + sinon.stub(App.db, 'setFilterConditions'); + sinon.stub(App.router.get('updateController'), 'updateClusterEnv'); + controller.set('isLoaded', false); + }); + + afterEach(function() { + App.router.get('updateController').updateClusterEnv.restore(); + App.db.setFilterConditions.restore(); + App.router.get('wizardWatcherController').getUser.restore(); + App.router.get('mainHostController').updateStatusCounters.restore(); + App.router.get('errorsHandlerController').loadErrorLogs.restore(); + App.router.get('userSettingsController').getAllUserSettings.restore(); + App.router.get('mainController').startPolling.restore(); + controller.loadAuthorizations.restore(); + controller.getAllHostNames.restore(); + controller.loadAmbariProperties.restore(); + controller.loadClusterInfo.restore(); + controller.restoreUpgradeState.restore(); + controller.loadClusterDataToModel.restore(); + }); + + it('loadAuthorizations should be called', function() { + controller.loadClusterData(); + expect(controller.loadAuthorizations.calledOnce).to.be.true; + }); + + it('getAllHostNames should be called', function() { + controller.loadClusterData(); + expect(controller.getAllHostNames.calledOnce).to.be.true; + }); + + it('loadAmbariProperties should be called', function() { + controller.loadClusterData(); + expect(controller.loadAmbariProperties.calledOnce).to.be.true; + }); + + it('getAllUserSettings should be called', function() { + controller.loadClusterData(); + expect(App.router.get('userSettingsController').getAllUserSettings.calledOnce).to.be.true; + }); + + it('loadErrorLogs should be called', function() { + controller.loadClusterData(); + expect(App.router.get('errorsHandlerController').loadErrorLogs.calledOnce).to.be.true; + }); + + it('updateStatusCounters should be called', function() { + controller.loadClusterData(); + expect(App.router.get('mainHostController').updateStatusCounters.calledOnce).to.be.true; + }); + + it('loadClusterInfo should be called', function() { + controller.loadClusterData(); + expect(controller.loadClusterInfo.calledOnce).to.be.true; + }); + + it('restoreUpgradeState should be called', function() { + controller.loadClusterData(); + expect(controller.restoreUpgradeState.calledOnce).to.be.true; + }); + + it('getUser should be called', function() { + controller.loadClusterData(); + expect(App.router.get('wizardWatcherController').getUser.calledOnce).to.be.true; + }); + + it('App.db.setFilterConditions should be called', function() { + controller.loadClusterData(); + expect(App.db.setFilterConditions.calledOnce).to.be.true; + }); + + it('loadClusterDataToModel should be called', function() { + controller.loadClusterData(); + expect(controller.loadClusterDataToModel.calledOnce).to.be.true; + }); + + it('updateClusterEnv should be called', function() { + controller.loadClusterData(); + expect(App.router.get('updateController').updateClusterEnv.calledOnce).to.be.true; + }); + + it('startPolling should be called', function() { + controller.set('isLoaded', true); + controller.loadClusterData(); + expect(App.router.get('mainController').startPolling.calledOnce).to.be.true; + }); + }); + + describe('#loadClusterInfo()', function() { + + beforeEach(function() { + sinon.stub(App.HttpClient, 'get'); + }); + + afterEach(function() { + App.HttpClient.get.restore(); + }); + + it('App.HttpClient.get should be called', function() { + controller.loadClusterInfo(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#loadClusterDataToModel()', function() { + + beforeEach(function() { + sinon.stub(controller, 'loadStackServiceComponents', function(callback) { + callback({items: [{ + StackServices: {} + }]}); + }); + sinon.stub(App.stackServiceMapper, 'mapStackServices'); + sinon.stub(App.config, 'setPreDefinedServiceConfigs'); + sinon.stub(controller, 'updateLoadStatus'); + sinon.stub(controller, 'loadServicesAndComponents'); + controller.loadClusterDataToModel(); + }); + + afterEach(function() { + controller.loadServicesAndComponents.restore(); + controller.updateLoadStatus.restore(); + controller.loadStackServiceComponents.restore(); + App.stackServiceMapper.mapStackServices.restore(); + App.config.setPreDefinedServiceConfigs.restore(); + }); + + it('loadStackServiceComponents should be called', function() { + expect(controller.loadStackServiceComponents.calledOnce).to.be.true; + }); + + it('App.stackServiceMapper.mapStackServices should be called', function() { + expect(App.stackServiceMapper.mapStackServices.calledWith({items: [ + { + StackServices: { + is_selected: true, + is_installed: false + } + } + ]})).to.be.true; + }); + + it('App.config.setPreDefinedServiceConfigs should be called', function() { + expect(App.config.setPreDefinedServiceConfigs.calledWith(true)).to.be.true; + }); + + it('updateLoadStatus should be called', function() { + expect(controller.updateLoadStatus.calledWith('stackComponents')).to.be.true; + }); + + it('loadServicesAndComponents should be called', function() { + expect(controller.loadServicesAndComponents.calledOnce).to.be.true; + }); + }); + + describe('#loadAlerts()', function() { + var updater = App.router.get('updateController'); + + beforeEach(function() { + sinon.stub(updater, 'updateAlertGroups', Em.clb); + sinon.stub(updater, 'updateAlertDefinitions', Em.clb); + sinon.stub(updater, 'updateAlertDefinitionSummary', Em.clb); + sinon.stub(updater, 'updateUnhealthyAlertInstances', Em.clb); + controller.loadAlerts(); + }); + + afterEach(function() { + updater.updateUnhealthyAlertInstances.restore(); + updater.updateAlertDefinitionSummary.restore(); + updater.updateAlertDefinitions.restore(); + updater.updateAlertGroups.restore(); + }); + + it('updateAlertGroups should be called', function() { + expect(updater.updateAlertGroups.calledOnce).to.be.true; + }); + + it('updateAlertDefinitions should be called', function() { + expect(updater.updateAlertDefinitions.calledOnce).to.be.true; + }); + + it('updateAlertDefinitionSummary should be called', function() { + expect(updater.updateAlertDefinitionSummary.calledOnce).to.be.true; + }); + + it('updateUnhealthyAlertInstances should be called', function() { + expect(updater.updateUnhealthyAlertInstances.calledOnce).to.be.true; + }); + + it('should set isAlertsLoaded to true', function() { + expect(controller.get('isAlertsLoaded')).to.be.true; + }); + }); + + describe('#loadConfigProperties()', function() { + + beforeEach(function() { + sinon.stub(App.config, 'loadConfigsFromStack').returns({ + complete: Em.clb + }); + sinon.stub(App.config, 'loadClusterConfigsFromStack').returns({ + complete: Em.clb + }); + }); + + afterEach(function() { + App.config.loadClusterConfigsFromStack.restore(); + App.config.loadConfigsFromStack.restore(); + }); + + it('App.config.loadConfigsFromStack should be called', function() { + controller.loadConfigProperties(); + expect(App.config.loadConfigsFromStack.calledOnce).to.be.true; + }); + + it('App.config.loadClusterConfigsFromStack should be called', function() { + controller.loadConfigProperties(); + expect(App.config.loadClusterConfigsFromStack.calledOnce).to.be.true; + }); + + it('isConfigsPropertiesLoaded should be true', function() { + controller.loadConfigProperties(); + expect(controller.get('isConfigsPropertiesLoaded')).to.be.true; + }); + }); + + describe('#loadServicesAndComponents()', function() { + var updater = App.router.get('updateController'); + + beforeEach(function() { + sinon.stub(updater, 'updateServices', Em.clb); + sinon.stub(controller, 'updateLoadStatus'); + sinon.stub(updater, 'updateHost', Em.clb); + sinon.stub(controller, 'loadAlerts'); + sinon.stub(controller, 'loadConfigProperties'); + sinon.stub(updater, 'updateComponentsState', Em.clb); + sinon.stub(updater, 'updateServiceMetric', Em.clb); + sinon.stub(updater, 'updateComponentConfig', Em.clb); + + controller.loadServicesAndComponents(); + }); + + afterEach(function() { + controller.loadConfigProperties.restore(); + controller.loadAlerts.restore(); + updater.updateHost.restore(); + updater.updateServices.restore(); + controller.updateLoadStatus.restore(); + updater.updateComponentsState.restore(); + updater.updateServiceMetric.restore(); + updater.updateComponentConfig.restore(); + }); + + it('updateServices should be called', function() { + expect(updater.updateServices.calledOnce).to.be.true; + }); + + it('updateLoadStatus should be called', function() { + expect(controller.updateLoadStatus.calledWith('services')).to.be.true; + }); + + it('updateHost should be called', function() { + expect(updater.updateHost.calledOnce).to.be.true; + }); + + it('isHostsLoaded should be true', function() { + expect(controller.get('isHostsLoaded')).to.be.true; + }); + + it('loadAlerts should be called', function() { + expect(controller.loadAlerts.calledOnce).to.be.true; + }); + + it('loadConfigProperties should be called', function() { + expect(controller.loadConfigProperties.calledOnce).to.be.true; + }); + + it('updateComponentsState should be called', function() { + expect(updater.updateComponentsState.calledOnce).to.be.true; + }); + + it('isComponentsStateLoaded should be true', function() { + expect(controller.get('isComponentsStateLoaded')).to.be.true; + }); + + it('updateServiceMetric should be called', function() { + expect(updater.updateServiceMetric.calledTwice).to.be.true; + }); + + it('isServiceMetricsLoaded should be true', function() { + expect(controller.get('isServiceMetricsLoaded')).to.be.true; + }); + + it('isHostComponentMetricsLoaded should be true', function() { + expect(controller.get('isHostComponentMetricsLoaded')).to.be.true; + }); + + it('updateComponentConfig should be called', function() { + expect(updater.updateComponentConfig.calledOnce).to.be.true; + }); + + it('isComponentsConfigLoaded should be true', function() { + expect(controller.get('isComponentsConfigLoaded')).to.be.true; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/test/controllers/global/configuration_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/configuration_controller_test.js b/ambari-web/test/controllers/global/configuration_controller_test.js index 5baac0e..11dfe0d 100644 --- a/ambari-web/test/controllers/global/configuration_controller_test.js +++ b/ambari-web/test/controllers/global/configuration_controller_test.js @@ -19,6 +19,7 @@ var App = require('app'); require('controllers/global/configuration_controller'); +var testHelpers = require('test/helpers'); describe('App.ConfigurationController', function () { @@ -131,4 +132,166 @@ describe('App.ConfigurationController', function () { }); }); }); + + describe('#getConfigsByTags()', function() { + + beforeEach(function() { + sinon.stub(App.db, 'getConfigs').returns([ + { + type: 't1', + tag: 'tag1' + } + ]); + this.mockCheck = sinon.stub(controller, 'checkTagsChanges'); + sinon.stub(controller, 'loadFromServer'); + sinon.stub(controller, 'loadFromDB'); + }); + + afterEach(function() { + App.db.getConfigs.restore(); + this.mockCheck.restore(); + controller.loadFromServer.restore(); + controller.loadFromDB.restore(); + }); + + it('checkTagsChanges should be called', function() { + controller.getConfigsByTags([]); + expect(controller.checkTagsChanges.calledWith([], [{ + siteName: 't1', + tagName: 'tag1' + }])).to.be.true; + }); + + it('loadFromServer should be called', function() { + this.mockCheck.returns(true); + controller.getConfigsByTags([]); + expect(controller.loadFromServer.calledWith([])).to.be.true; + }); + + it('loadFromDB should be called', function() { + this.mockCheck.returns(false); + controller.getConfigsByTags([{siteName: 'site1'}]); + expect(controller.loadFromDB.calledWith(['site1'])).to.be.true; + }); + }); + + describe('#loadFromServer()', function() { + + beforeEach(function() { + sinon.stub(controller, 'loadConfigTags').returns({ + done: function(callback) { + callback({ + Clusters: { + desired_configs: { + 's1': { + siteName: 's1', + tag: 'tag2' + } + } + } + }); + } + }); + sinon.stub(controller, 'loadConfigsByTags'); + }); + + afterEach(function() { + controller.loadConfigTags.restore(); + controller.loadConfigsByTags.restore(); + }); + + it('tags data is correct', function() { + expect(controller.loadFromServer([{tagName: 'tag1', siteName: 's1'}])).to.be.an.object; + expect(controller.loadConfigsByTags.calledWith([{tagName: 'tag1', siteName: 's1'}])).to.be.true; + }); + + it('tags data is corrupted', function() { + expect(controller.loadFromServer([{siteName: 's1'}])).to.be.an.object; + expect(controller.loadConfigsByTags.calledWith([{tagName: 'tag2', siteName: 's1'}])).to.be.true; + }); + }); + + describe('#loadConfigsByTags()', function() { + var dfd = { + resolve: Em.K + }; + + beforeEach(function() { + sinon.stub(App.config, 'loadConfigsByTags').returns({ + done: function(callback) { + callback({items: [{}]}); + return { + complete: Em.clb + } + } + }); + sinon.stub(controller, 'saveToDB'); + sinon.spy(dfd, 'resolve'); + controller.loadConfigsByTags([], dfd); + }); + + afterEach(function() { + App.config.loadConfigsByTags.restore(); + controller.saveToDB.restore(); + dfd.resolve.restore(); + }); + + it('saveToDB should be called', function() { + expect(controller.saveToDB.calledWith([{}])).to.be.true; + }); + + it('Deferred should be resolved', function() { + expect(dfd.resolve.calledWith([{}])).to.be.true; + }); + }); + + describe('#loadConfigTags()', function() { + + it('App.ajax.send should be called', function() { + controller.loadConfigTags(); + var args = testHelpers.findAjaxRequest('name', 'config.tags'); + expect(args).to.exist; + }); + }); + + describe('#saveToDB()', function() { + + beforeEach(function() { + sinon.stub(App.db, 'getConfigs').returns([{ + type: 't1' + }]); + sinon.stub(App.db, 'setConfigs'); + }); + + afterEach(function() { + App.db.getConfigs.restore(); + App.db.setConfigs.restore(); + }); + + it('App.db.setConfigs should be called', function() { + var loadedConfigs = [ + { + type: 't1', + tag: 'tag1', + properties: {}, + properties_attributes: {} + }, + { + type: 't2' + } + ]; + controller.saveToDB(loadedConfigs); + expect(JSON.stringify(App.db.setConfigs.getCall(0).args[0])).to.be.equal(JSON.stringify([ + { + type: 't1', + tag: 'tag1', + properties: {}, + properties_attributes: {} + }, + { + type: 't2' + } + ])); + }); + }); }); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/test/controllers/global/errors_handler_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/errors_handler_controller_test.js b/ambari-web/test/controllers/global/errors_handler_controller_test.js index 2a726ee..aa98d09 100644 --- a/ambari-web/test/controllers/global/errors_handler_controller_test.js +++ b/ambari-web/test/controllers/global/errors_handler_controller_test.js @@ -67,4 +67,14 @@ describe('App.ErrorsHandlerController', function () { expect(args[0]).to.be.equal('errors'); }); }); + + describe("#getUserPrefSuccessCallback()", function () { + + it("should set errors to localStorage", function() { + controller.getUserPrefSuccessCallback({data: {}}); + expect(localStorage.getObject('errors')).to.be.eql({ + data: {} + }) + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/test/controllers/global/update_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/update_controller_test.js b/ambari-web/test/controllers/global/update_controller_test.js index dc57a57..2a9d020 100644 --- a/ambari-web/test/controllers/global/update_controller_test.js +++ b/ambari-web/test/controllers/global/update_controller_test.js @@ -32,6 +32,11 @@ describe('App.UpdateController', function () { beforeEach(function () { c = App.UpdateController.create(); + sinon.stub(App.HttpClient, 'get'); + }); + + afterEach(function() { + App.HttpClient.get.restore(); }); App.TestAliases.testAsComputedAlias(App.UpdateController.create(), 'clusterName', 'App.router.clusterController.clusterName', 'string'); @@ -443,6 +448,14 @@ describe('App.UpdateController', function () { describe('#computeParameters', function () { + beforeEach(function() { + sinon.stub(App.router.get('mainHostComboSearchBoxController'), 'generateQueryParam').returns('combo'); + }); + + afterEach(function() { + App.router.get('mainHostComboSearchBoxController').generateQueryParam.restore(); + }); + Em.A([ { q: [{ @@ -454,6 +467,22 @@ describe('App.UpdateController', function () { }, { q: [{ + type: 'CUSTOM', + key: '{0} - {1}', + value: [1, 2] + }], + result: '1 - 2' + }, + { + q: [{ + type: 'COMBO', + key: '', + value: [] + }], + result: 'combo' + }, + { + q: [{ type: 'MULTIPLE', key: 'k', value: [1, 2] @@ -534,9 +563,102 @@ describe('App.UpdateController', function () { var result = c.computeParameters(test.q); expect(result).to.be.equal(test.result); }); + }); + }); + + describe('#preLoadHosts()', function() { + + beforeEach(function() { + sinon.stub(c, 'getHostByHostComponents'); + }); + + afterEach(function() { + c.getHostByHostComponents.restore(); + }); + + it('getHostByHostComponents should be called', function() { + c.set('queryParams.Hosts', [{isComponentRelatedFilter: true}]); + expect(c.preLoadHosts(Em.K)).to.be.true; + expect(c.getHostByHostComponents.calledOnce).to.be.true; + }); + + it('getHostByHostComponents should not be called', function() { + c.set('queryParams.Hosts', []); + expect(c.preLoadHosts(Em.K)).to.be.false; + expect(c.getHostByHostComponents.calledOnce).to.be.false; + }); + }); + + describe('#getHostByHostComponents', function() { + it('App.ajax.send should be called', function() { + var args = testHelpers.findAjaxRequest('name', 'hosts.host_components.pre_load'); + expect(args).to.exists; + }); + }); + + describe('#updateServices()', function() { + it('App.HttpClient.get should be called', function() { + c.updateServices(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateComponentConfig()', function() { + it('App.HttpClient.get should be called', function() { + c.updateComponentConfig(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateComponentsState()', function() { + it('App.HttpClient.get should be called', function() { + c.updateComponentsState(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateAlertDefinitions()', function() { + it('App.HttpClient.get should be called', function() { + c.updateAlertDefinitions(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateUnhealthyAlertInstances()', function() { + it('App.HttpClient.get should be called', function() { + c.updateUnhealthyAlertInstances(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateAlertDefinitionSummary()', function() { + it('App.HttpClient.get should be called', function() { + c.updateAlertDefinitionSummary(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); + }); + + describe('#updateAlertGroups()', function() { + it('App.HttpClient.get should be called', function() { + c.updateAlertGroups(); + expect(App.HttpClient.get.calledOnce).to.be.true; }); + }); + describe('#updateAlertNotifications()', function() { + it('App.HttpClient.get should be called', function() { + c.updateAlertNotifications(); + expect(App.HttpClient.get.calledOnce).to.be.true; + }); }); + describe('#loadClusterConfig()', function() { + + it('App.ajax.send should be called', function() { + c.loadClusterConfig(); + var args = testHelpers.findAjaxRequest('name', 'config.tags.site'); + expect(args).to.exists; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/98a83c5f/ambari-web/test/controllers/global/user_settings_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/user_settings_controller_test.js b/ambari-web/test/controllers/global/user_settings_controller_test.js index 5ae17f8..f68c109 100644 --- a/ambari-web/test/controllers/global/user_settings_controller_test.js +++ b/ambari-web/test/controllers/global/user_settings_controller_test.js @@ -17,6 +17,7 @@ */ var App = require('app'); +var testHelpers = require('test/helpers'); describe('App.UserSettingsController', function () { var controller; @@ -58,4 +59,303 @@ describe('App.UserSettingsController', function () { }); }); + describe("#dataLoading()", function () { + + beforeEach(function() { + sinon.stub(controller, 'getUserPref').returns({ + complete: Em.clb + }); + }); + + afterEach(function() { + controller.getUserPref.restore(); + }); + + it("should return promise with preferences", function() { + controller.set('currentPrefObject', {data: {}}); + var promise = controller.dataLoading(); + promise.done(function(result) { + expect(result).to.be.eql({data: {}}); + }); + expect(controller.get('currentPrefObject')).to.be.null; + }); + }); + + describe("#getUserPrefErrorCallback()", function () { + + beforeEach(function() { + sinon.stub(controller, 'updateUserPrefWithDefaultValues'); + }); + + afterEach(function() { + controller.updateUserPrefWithDefaultValues.restore(); + }); + + it("updateUserPrefWithDefaultValues should be called", function() { + controller.getUserPrefErrorCallback({status: 404}); + expect(controller.updateUserPrefWithDefaultValues.calledOnce).to.be.true; + }); + + it("updateUserPrefWithDefaultValues should not be called", function() { + controller.getUserPrefErrorCallback({status: 200}); + expect(controller.updateUserPrefWithDefaultValues.called).to.be.false; + }); + }); + + describe("#getAllUserSettings()", function () { + + beforeEach(function() { + sinon.stub(controller, 'dataLoading').returns({ + done: function(callback) { + callback({}); + } + }); + sinon.stub(controller, 'postUserPref'); + controller.reopen({ + userSettingsKeys: { + key1: { + defaultValue: 'val' + } + } + }); + controller.getAllUserSettings(); + }); + + afterEach(function() { + controller.dataLoading.restore(); + controller.postUserPref.restore(); + }); + + it("postUserPref should be called", function() { + expect(controller.postUserPref.calledWith('key1', 'val')).to.be.true; + }); + + it("userSettings should be set", function() { + expect(controller.get('userSettings')).to.be.eql({key1: 'val'}); + }); + }); + + describe('#updateUserPrefWithDefaultValues()', function() { + + beforeEach(function() { + sinon.stub(controller, 'postUserPref'); + controller.reopen({ + userSettingsKeys: { + key1: { + name: 'n1', + defaultValue: 'val' + } + } + }); + }); + + afterEach(function() { + controller.postUserPref.restore(); + }); + + it('postUserPref should be called', function() { + controller.updateUserPrefWithDefaultValues({}, true); + expect(controller.postUserPref.calledWith('key1', 'val')).to.be.true; + }); + }); + + describe('#showSettingsPopup()', function() { + + beforeEach(function() { + this.mockAuthorized = sinon.stub(App, 'isAuthorized'); + sinon.stub(controller, 'dataLoading').returns({ + done: Em.clb + }); + sinon.stub(controller, 'loadPrivileges').returns({ + complete: Em.clb + }); + sinon.stub(controller, '_showSettingsPopup'); + }); + + afterEach(function() { + controller.dataLoading.restore(); + this.mockAuthorized.restore(); + controller.loadPrivileges.restore(); + controller._showSettingsPopup.restore(); + }); + + it('dataLoading should not be called', function() { + this.mockAuthorized.returns(false); + controller.showSettingsPopup(); + expect(controller.dataLoading).to.not.be.called; + }); + + it('_showSettingsPopup should be called', function() { + this.mockAuthorized.returns(true); + controller.showSettingsPopup(); + expect(controller.dataLoading).to.be.calledOnce; + expect(controller.loadPrivileges).to.be.calledOnce; + expect(controller._showSettingsPopup).to.be.calledonce; + }); + }); + + describe('#loadPrivileges()', function() { + + beforeEach(function() { + sinon.stub(App.db, 'getLoginName').returns('user'); + }); + + afterEach(function() { + App.db.getLoginName.restore(); + }); + + it('App.ajax.send should be called', function() { + controller.loadPrivileges(); + var args = testHelpers.findAjaxRequest('name', 'router.user.privileges'); + expect(args[0]).to.be.eql({ + name: 'router.user.privileges', + sender: controller, + data: { + userName: 'user' + }, + success: 'loadPrivilegesSuccessCallback' + }); + }); + }); + + describe('#postUserPref()', function() { + + it('short key', function() { + controller.postUserPref('key1', 'val1'); + expect(controller.get('userSettings.key1')).to.be.equal('val1'); + }); + + it('key with prefix', function() { + controller.postUserPref('userSettingsKeys.key2', 'val2'); + expect(controller.get('userSettings.key2')).to.be.equal('val2'); + }); + }); + + describe('#loadPrivilegesSuccessCallback()', function() { + + beforeEach(function() { + this.mock = sinon.stub(controller, 'parsePrivileges'); + }); + + afterEach(function() { + this.mock.restore(); + }); + + it('should set privilege info when data present', function() { + this.mock.returns({ + clusters: { + 'c1': {} + }, + views: { + 'v1': { + privileges: {}, + version: 'ver1', + view_name: 'view1' + } + } + }); + controller.loadPrivilegesSuccessCallback({items: [{}]}); + expect(JSON.stringify(controller.get('privileges'))).to.be.equal(JSON.stringify({ + clusters: [ + { + name: 'c1', + privileges: {} + } + ], + views: [ + { + instance_name: 'v1', + privileges: {}, + version: 'ver1', + view_name: 'view1' + } + ] + })); + expect(controller.get('noClusterPriv')).to.be.false; + expect(controller.get('noViewPriv')).to.be.false; + expect(controller.get('hidePrivileges')).to.be.false; + }); + + it('should set privilege info when data is empty', function() { + this.mock.returns({ + clusters: {}, + views: {} + }); + controller.loadPrivilegesSuccessCallback({items: []}); + expect(controller.get('privileges')).to.be.null; + expect(controller.get('noClusterPriv')).to.be.true; + expect(controller.get('noViewPriv')).to.be.true; + expect(controller.get('hidePrivileges')).to.be.true; + }); + }); + + describe('#parsePrivileges()', function() { + + it('should parse privileges from data', function() { + var data = { + items: [ + { + PrivilegeInfo: { + type: 'CLUSTER', + cluster_name: 'c1', + clusters: {}, + permission_label: 'perm1' + } + }, + { + PrivilegeInfo: { + type: 'VIEW', + instance_name: 'c1', + view_name: 'v1', + version: 'ver1', + views: {}, + permission_label: 'perm1' + } + } + ] + }; + expect(controller.parsePrivileges(data)).to.be.eql({ + "clusters": { + "c1": [ + "perm1" + ] + }, + "views": { + "c1": { + "privileges": [ + "perm1" + ], + "version": "ver1", + "view_name": "v1" + } + } + }) + }); + }); + + describe('#_showSettingsPopup()', function() { + + beforeEach(function() { + sinon.stub(App.ModalPopup, 'show'); + sinon.stub(App, 'showAlertPopup'); + }); + + afterEach(function() { + App.ModalPopup.show.restore(); + App.showAlertPopup.restore(); + }); + + it('App.ModalPopup.show should be called', function() { + controller.set('userSettingsKeys', {show_bg: {name: 'n1'}}); + controller._showSettingsPopup({n1: {}}); + expect(App.ModalPopup.show).to.be.calledOnce; + }); + + it('App.showAlertPopup should be called', function() { + controller.set('userSettingsKeys', {show_bg: {name: 'n1'}}); + controller._showSettingsPopup({}); + expect(App.showAlertPopup).to.be.calledOnce; + }); + }); + }); \ No newline at end of file