AMBARI-14629 Cover Alerts views 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/ce192a48 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ce192a48 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ce192a48 Branch: refs/heads/branch-dev-patch-upgrade Commit: ce192a4884e4cb60157d813b3d990b7926847372 Parents: a688559 Author: Andrii Tkach <[email protected]> Authored: Wed Jan 13 13:29:04 2016 +0200 Committer: Andrii Tkach <[email protected]> Committed: Wed Jan 13 13:53:26 2016 +0200 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 2 + ambari-web/app/messages.js | 1 + .../details/host_components/decommissionable.js | 43 +- .../host_components/install_component.js | 9 +- .../main/alerts/definition_configs_view.js | 5 + .../main/alerts/definition_details_view.js | 37 +- .../main/alerts/manage_alert_groups_view.js | 21 +- .../alerts/manage_alert_notifications_view.js | 26 +- .../host_components/decommissionable_test.js | 455 +++++++++++++++++++ .../host_components/install_component_test.js | 207 +++++++++ .../views/main/alert_definitions_view_test.js | 2 +- .../main/alerts/definition_configs_view_test.js | 123 +++++ .../main/alerts/definition_details_view_test.js | 341 +++++++++++++- .../alerts/manage_alert_groups_view_test.js | 197 ++++++++ .../manage_alert_notifications_view_test.js | 267 +++++++++-- 15 files changed, 1625 insertions(+), 111 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/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 3362984..031a939 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -150,6 +150,7 @@ var files = [ 'test/mixins/common/table_server_view_mixin_test', 'test/mixins/common/widget_mixin_test', 'test/mixins/main/host/details/host_components/decommissionable_test', + 'test/mixins/main/host/details/host_components/install_component_test', 'test/mixins/main/service/configs/widget_popover_support_test', 'test/mixins/main/service/configs/config_overridable_test', 'test/mixins/routers/redirections_test', @@ -216,6 +217,7 @@ var files = [ 'test/views/main/alerts/manage_alert_groups_view_test', 'test/views/main/alerts/manage_alert_notifications_view_test', 'test/views/main/alerts/definition_details_view_test', + 'test/views/main/alerts/definition_configs_view_test', 'test/views/main/alerts/add_alert_definition/step1_view_test', 'test/views/main/alerts/add_alert_definition/step3_view_test', 'test/views/main/alerts/manage_alert_groups/select_definitions_popup_body_view_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index c17b89a..2f28a75 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -300,6 +300,7 @@ Em.I18n.translations = { 'common.timeout.warning.popup.secondary': 'Log Out Now', 'common.openNewWindow': 'Open in New Window', 'common.fullLogPopup.clickToCopy': 'Click to Copy', + 'common.nothingToDelete': 'Nothing to delete', 'models.alert_instance.tiggered.verbose': "Occurred on {0} <br> Checked on {1}", 'models.alert_definition.triggered.verbose': "Occurred on {0}", http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/mixins/main/host/details/host_components/decommissionable.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/host/details/host_components/decommissionable.js b/ambari-web/app/mixins/main/host/details/host_components/decommissionable.js index 9febc51..0480c0b 100644 --- a/ambari-web/app/mixins/main/host/details/host_components/decommissionable.js +++ b/ambari-web/app/mixins/main/host/details/host_components/decommissionable.js @@ -34,21 +34,21 @@ App.Decommissionable = Em.Mixin.create({ /** * Is component in decommission process right know - * @type {bool} + * @type {boolean} */ - isComponentDecommissioning: null, + isComponentDecommissioning: false, /** * May component be decommissioned - * @type {bool} + * @type {boolean} */ - isComponentDecommissionAvailable: null, + isComponentDecommissionAvailable: false, /** * May component be recommissioned - * @type {bool} + * @type {boolean} */ - isComponentRecommissionAvailable: null, + isComponentRecommissionAvailable: false, /** * Component with stopped masters can't be docommissioned @@ -70,12 +70,14 @@ App.Decommissionable = Em.Mixin.create({ /** * Tooltip message shows if decommission/recommission is disabled * when masters for current component is down + * @type {string} */ decommissionTooltipMessage: function () { if (this.get('isComponentDecommissionDisable') && (this.get('isComponentRecommissionAvailable') || this.get('isComponentDecommissionAvailable'))) { var decom = this.get('isComponentRecommissionAvailable') ? Em.I18n.t('common.recommission') : Em.I18n.t('common.decommission'); return Em.I18n.t('hosts.decommission.tooltip.warning').format(decom, App.format.role(this.get('componentForCheckDecommission'))); } + return ''; }.property('isComponentDecommissionDisable', 'isComponentRecommissionAvailable', 'isComponentDecommissionAvailable', 'componentForCheckDecommission'), /** * Recalculated component status based on decommission @@ -163,7 +165,7 @@ App.Decommissionable = Em.Mixin.create({ */ getDesiredAdminStateSuccessCallback: function (response) { var status = response.HostRoles.desired_admin_state; - if (status != null) { + if (!Em.isNone(status)) { this.setDesiredAdminState(status); return status; } @@ -206,7 +208,7 @@ App.Decommissionable = Em.Mixin.create({ */ getDecommissionStatusSuccessCallback: function (response) { var statusObject = response.ServiceComponentInfo; - if (statusObject != null) { + if (!Em.isNone(statusObject)) { statusObject.component_state = response.host_components[0].HostRoles.state; this.setDecommissionStatus(statusObject); return statusObject; @@ -260,24 +262,33 @@ App.Decommissionable = Em.Mixin.create({ */ doBlinking: function () { var workStatus = this.get('workStatus'); - var self = this; var pulsate = [App.HostComponentStatus.starting, App.HostComponentStatus.stopping, App.HostComponentStatus.installing].contains(workStatus); + if (!pulsate) { var component = this.get('content'); - if (component && workStatus != "INSTALLED") { + if (component && workStatus !== "INSTALLED") { pulsate = this.get('isDecommissioning'); } } - if (pulsate && !self.get('isBlinking')) { - self.set('isBlinking', true); - uiEffects.pulsate(self.$('.components-health'), 1000, function () { - self.set('isBlinking', false); - self.doBlinking(); - }); + if (pulsate && !this.get('isBlinking')) { + this.set('isBlinking', true); + this.pulsate(); } }, /** + * perform the pulsation + */ + pulsate: function() { + var self = this; + + uiEffects.pulsate(self.$('.components-health'), 1000, function () { + self.set('isBlinking', false); + self.doBlinking(); + }); + }, + + /** * Start blinking when host component is starting/stopping/decommissioning */ startBlinking: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/mixins/main/host/details/host_components/install_component.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/host/details/host_components/install_component.js b/ambari-web/app/mixins/main/host/details/host_components/install_component.js index 4b03b69..58f0dca 100644 --- a/ambari-web/app/mixins/main/host/details/host_components/install_component.js +++ b/ambari-web/app/mixins/main/host/details/host_components/install_component.js @@ -101,7 +101,7 @@ App.InstallComponent = Em.Mixin.create({ updateAndCreateServiceComponent: function (componentName) { var self = this; var dfd = $.Deferred(); - var updater = App.router.get('updateController'); + var updater = App.router.get('updateController'); updater.updateComponentsState(function () { updater.updateServiceMetric(function () { self.createServiceComponent(componentName, dfd); @@ -112,9 +112,9 @@ App.InstallComponent = Em.Mixin.create({ /** * - * @param componentName - * @param dfd - * @returns {*} + * @param {string} componentName + * @param {$.Deferred} dfd + * @returns {$.ajax|null} */ createServiceComponent: function (componentName, dfd) { var allServiceComponents = []; @@ -125,6 +125,7 @@ App.InstallComponent = Em.Mixin.create({ }, this); if (allServiceComponents.contains(componentName)) { dfd.resolve(); + return null; } else { return App.ajax.send({ name: 'common.create_component', http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/views/main/alerts/definition_configs_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/definition_configs_view.js b/ambari-web/app/views/main/alerts/definition_configs_view.js index 16f283d..d909367 100644 --- a/ambari-web/app/views/main/alerts/definition_configs_view.js +++ b/ambari-web/app/views/main/alerts/definition_configs_view.js @@ -32,6 +32,11 @@ App.AlertDefinitionConfigsView = Em.View.extend({ canEdit: true, /** + * @type {string} + */ + alertDefinitionType: '', + + /** * List of classes applied to all inputs * @type {String} */ http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/views/main/alerts/definition_details_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/definition_details_view.js b/ambari-web/app/views/main/alerts/definition_details_view.js index dc3f401..39fcf55 100644 --- a/ambari-web/app/views/main/alerts/definition_details_view.js +++ b/ambari-web/app/views/main/alerts/definition_details_view.js @@ -45,25 +45,30 @@ App.MainAlertDefinitionDetailsView = App.TableView.extend({ willInsertElement: function () { this._super(); this.get('controller').clearStep(); - var self = this, - updater = App.router.get('updateController'); - if (self.get('controller.content.isLoaded')) { - self.set('isLoaded', true); - self.get('controller').loadAlertInstances(); + + if (this.get('controller.content.isLoaded')) { + this.set('isLoaded', true); + this.get('controller').loadAlertInstances(); + } else { + this.loadDefinitionDetails(); } - else { - updater.updateAlertGroups(function () { - updater.updateAlertDefinitions(function () { - updater.updateAlertDefinitionSummary(function () { - self.set('isLoaded', true); - // App.AlertDefinition doesn't represents real models - // Real model (see AlertDefinition types) should be used - self.set('controller.content', App.AlertDefinition.find().findProperty('id', parseInt(self.get('controller.content.id')))); - self.get('controller').loadAlertInstances(); - }); + }, + + loadDefinitionDetails: function() { + var self = this, + updater = App.router.get('updateController'); + + updater.updateAlertGroups(function () { + updater.updateAlertDefinitions(function () { + updater.updateAlertDefinitionSummary(function () { + self.set('isLoaded', true); + // App.AlertDefinition doesn't represents real models + // Real model (see AlertDefinition types) should be used + self.set('controller.content', App.AlertDefinition.find(parseInt(self.get('controller.content.id')))); + self.get('controller').loadAlertInstances(); }); }); - } + }); }, didInsertElement: function () { http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/views/main/alerts/manage_alert_groups_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/manage_alert_groups_view.js b/ambari-web/app/views/main/alerts/manage_alert_groups_view.js index 1872ad1..068edd0 100644 --- a/ambari-web/app/views/main/alerts/manage_alert_groups_view.js +++ b/ambari-web/app/views/main/alerts/manage_alert_groups_view.js @@ -120,14 +120,11 @@ App.MainAlertsManageAlertGroupView = Em.View.extend({ addDefinitionTooltip: function () { if (this.get('controller.selectedAlertGroup.default')) { return Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinitionToDefault'); + } else if (this.get('controller.selectedAlertGroup.isAddDefinitionsDisabled')) { + return Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinitionDisabled'); + } else { + return Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinition'); } - else - if (this.get('controller.selectedAlertGroup.isAddDefinitionsDisabled')) { - return Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinitionDisabled'); - } - else { - return Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinition'); - } }.property('controller.selectedAlertGroup.default', 'controller.selectedAlertGroup.isAddDefinitionsDisabled'), /** @@ -137,13 +134,11 @@ App.MainAlertsManageAlertGroupView = Em.View.extend({ removeDefinitionTooltip: function () { if (this.get('controller.selectedAlertGroup.default')) { return Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeDefinitionDisabled'); + } else if (this.get('controller.isDeleteDefinitionsDisabled')) { + return Em.I18n.t('common.nothingToDelete'); + } else { + return Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeDefinition'); } - else - if (this.get('controller.isDeleteDefinitionsDisabled')) { - return 'Nothing to delete'; - } else { - return Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeDefinition'); - } }.property('controller.selectedAlertGroup.default', 'controller.isDeleteDefinitionsDisabled') }); http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/app/views/main/alerts/manage_alert_notifications_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/manage_alert_notifications_view.js b/ambari-web/app/views/main/alerts/manage_alert_notifications_view.js index e6e2403..3f0bf2f 100644 --- a/ambari-web/app/views/main/alerts/manage_alert_notifications_view.js +++ b/ambari-web/app/views/main/alerts/manage_alert_notifications_view.js @@ -31,12 +31,24 @@ App.ManageAlertNotificationsView = Em.View.extend({ return this.get('controller.selectedAlertNotification.groups').toArray().mapProperty('displayName').join(', '); }.property('controller.selectedAlertNotification', 'controller.selectedAlertNotification.groups.@each', 'controller.isLoaded'), + /** + * @type {boolean} + */ isAddButtonDisabled: true, + /** + * @type {boolean} + */ isEditButtonDisabled: true, + /** + * @type {boolean} + */ isRemoveButtonDisabled: true, + /** + * @type {boolean} + */ isDuplicateButtonDisabled: true, /** @@ -55,6 +67,9 @@ App.ManageAlertNotificationsView = Em.View.extend({ return this.get('controller.selectedAlertNotification.properties')['ambari.dispatch.recipients']; }.property('controller.selectedAlertNotification.properties'), + /** + * @type {string} + */ severities: function () { return this.get('controller.selectedAlertNotification.alertStates').join(', '); }.property('controller.selectedAlertNotification.alertStates'), @@ -96,17 +111,16 @@ App.ManageAlertNotificationsView = Em.View.extend({ if (notifications && notifications.length) { this.set('selectedAlertNotification', this.get('controller.selectedAlertNotification') || notifications[0]); this.buttonObserver(); - } else { - if(!App.isOperator) - { - this.set('isAddButtonDisabled',false); - } + } else { + if (!App.isOperator) { + this.set('isAddButtonDisabled', false); + } this.set('selectedAlertNotification', null); } Em.run.later(this, function () { App.tooltip(this.$("[rel='button-info']")); App.tooltip(this.$("[rel='button-info-dropdown']"), {placement: 'left'}); - }, 50) ; + }, 50); } }.observes('controller.isLoaded'), http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js b/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js index 2d94d42..e0ee689 100644 --- a/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js +++ b/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js @@ -17,6 +17,7 @@ */ var App = require('app'); +var uiEffects = require('utils/ui_effects'); require('mixins/main/host/details/host_components/decommissionable'); @@ -37,6 +38,7 @@ describe('App.Decommissionable', function () { beforeEach(function () { decommissionable = Em.Object.create(App.Decommissionable); + decommissionable.set('$', Em.K); }); describe('#decommissionView.text', function () { @@ -57,4 +59,457 @@ describe('App.Decommissionable', function () { }); + describe("#isComponentDecommissionDisable", function() { + + beforeEach(function() { + decommissionable.set('componentForCheckDecommission', 'MC1'); + decommissionable.set('content', Em.Object.create({service: Em.Object.create()})); + }); + + it("masterComponent is absent, service workStatus is STARTED", function() { + decommissionable.set('content.service.hostComponents', []); + decommissionable.set('content.service.workStatus', App.HostComponentStatus.started); + expect(decommissionable.get('isComponentDecommissionDisable')).to.be.false; + }); + + it("masterComponent is absent, service workStatus is STOPPED", function() { + decommissionable.set('content.service.hostComponents', []); + decommissionable.set('content.service.workStatus', App.HostComponentStatus.stopped); + expect(decommissionable.get('isComponentDecommissionDisable')).to.be.true; + }); + + it("masterComponent is present, component workStatus is STARTED", function() { + decommissionable.set('content.service.hostComponents', [Em.Object.create({ + componentName: 'MC1', + workStatus: App.HostComponentStatus.started + })]); + decommissionable.set('content.service.workStatus', App.HostComponentStatus.started); + expect(decommissionable.get('isComponentDecommissionDisable')).to.be.false; + }); + + it("masterComponent is present, component workStatus is STOPPED", function() { + decommissionable.set('content.service.hostComponents', [Em.Object.create({ + componentName: 'MC1', + workStatus: App.HostComponentStatus.stopped + })]); + decommissionable.set('content.service.workStatus', App.HostComponentStatus.started); + expect(decommissionable.get('isComponentDecommissionDisable')).to.be.true; + }); + }); + + describe("#isRestartableComponent", function() { + + beforeEach(function() { + sinon.stub(App, 'get').returns(['C2']); + }); + afterEach(function() { + App.get.restore(); + }); + + var testCases = [ + { + input: { + isDecomissionable: false, + componentName: 'C1' + }, + expected: false + }, + { + input: { + isDecomissionable: true, + componentName: 'C1' + }, + expected: false + }, + { + input: { + isDecomissionable: false, + componentName: 'C2' + }, + expected: false + }, + { + input: { + isDecomissionable: true, + componentName: 'C2' + }, + expected: true + } + ]; + + testCases.forEach(function(test) { + it("isDecomissionable = " + test.input.isDecomissionable + "; " + + "componentName=" + test.input.componentName, function() { + decommissionable.setProperties({ + isComponentDecommissionAvailable: test.input.isDecomissionable, + content: Em.Object.create({ + componentName: test.input.componentName + }) + }); + expect(decommissionable.get('isRestartableComponent')).to.equal(test.expected); + }); + }, this); + }); + + describe("#decommissionTooltipMessage", function() { + + beforeEach(function() { + sinon.stub(App.format, 'role').returns('role'); + }); + afterEach(function() { + App.format.role.restore(); + }); + + var testCases = [ + { + input: { + isComponentDecommissionDisable: false, + isComponentRecommissionAvailable: false, + isComponentDecommissionAvailable: false + }, + expected: '' + }, + { + input: { + isComponentDecommissionDisable: true, + isComponentRecommissionAvailable: false, + isComponentDecommissionAvailable: false + }, + expected: '' + }, + { + input: { + isComponentDecommissionDisable: true, + isComponentRecommissionAvailable: true, + isComponentDecommissionAvailable: false + }, + expected: Em.I18n.t('hosts.decommission.tooltip.warning').format(Em.I18n.t('common.recommission'), 'role') + }, + { + input: { + isComponentDecommissionDisable: true, + isComponentRecommissionAvailable: false, + isComponentDecommissionAvailable: true + }, + expected: Em.I18n.t('hosts.decommission.tooltip.warning').format(Em.I18n.t('common.decommission'), 'role') + } + ]; + + testCases.forEach(function(test) { + it("isComponentDecommissionDisable = " + test.input.isComponentDecommissionDisable + '; ' + + "isComponentRecommissionAvailable = " + test.input.isComponentRecommissionAvailable + '; ' + + "isComponentDecommissionAvailable = " + test.input.isComponentDecommissionAvailable + , function() { + decommissionable.reopen({ + isComponentDecommissionDisable: test.input.isComponentDecommissionDisable, + isComponentRecommissionAvailable: test.input.isComponentRecommissionAvailable, + isComponentDecommissionAvailable: test.input.isComponentDecommissionAvailable + }); + expect(decommissionable.get('decommissionTooltipMessage')).to.equal(test.expected); + }); + }, this); + }); + + describe("#loadComponentDecommissionStatus()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, 'getDesiredAdminState'); + }); + afterEach(function() { + decommissionable.getDesiredAdminState.restore(); + }); + + it("getDesiredAdminState should be called", function() { + decommissionable.loadComponentDecommissionStatus(); + expect(decommissionable.getDesiredAdminState.calledOnce).to.be.true; + }); + }); + + describe("#getDesiredAdminStateSuccessCallback()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, 'setDesiredAdminState'); + }); + afterEach(function() { + decommissionable.setDesiredAdminState.restore(); + }); + + it("desired_admin_state is null", function() { + var response = { + HostRoles: { + desired_admin_state: null + } + }; + + expect(decommissionable.getDesiredAdminStateSuccessCallback(response)).to.be.null; + expect(decommissionable.setDesiredAdminState.called).to.be.false; + }); + + it("setDesiredAdminState should be called", function() { + var response = { + HostRoles: { + desired_admin_state: "STATUS" + } + }; + + expect(decommissionable.getDesiredAdminStateSuccessCallback(response)).to.equal('STATUS'); + expect(decommissionable.setDesiredAdminState.calledWith('STATUS')).to.be.true; + }); + }); + + describe("#getDecommissionStatus()", function() { + + beforeEach(function() { + sinon.stub(App.ajax, 'send'); + }); + afterEach(function() { + App.ajax.send.restore(); + }); + + it("App.ajax.send should be called", function() { + decommissionable.setProperties({ + componentForCheckDecommission: 'C1', + content: Em.Object.create({ + hostName: 'host1', + service: Em.Object.create({ + serviceName: 'S1' + }) + }) + }); + decommissionable.getDecommissionStatus(); + expect(App.ajax.send.getCall(0).args[0]).to.eql({ + name: 'host.host_component.decommission_status', + sender: decommissionable, + data: { + hostName: 'host1', + componentName: 'C1', + serviceName: 'S1' + }, + success: 'getDecommissionStatusSuccessCallback', + error: 'getDecommissionStatusErrorCallback' + }); + }); + }); + + describe("#getDecommissionStatusSuccessCallback()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, 'setDecommissionStatus'); + }); + afterEach(function() { + decommissionable.setDecommissionStatus.restore(); + }); + + it("ServiceComponentInfo is null", function() { + var response = { + ServiceComponentInfo: null + }; + + expect(decommissionable.getDecommissionStatusSuccessCallback(response)).to.be.null; + expect(decommissionable.setDecommissionStatus.called).to.be.false; + }); + + it("setDecommissionStatus should be called", function() { + var response = { + ServiceComponentInfo: {}, + host_components: [{ + HostRoles: { + state: 'STATE' + } + }] + }; + var statusObject = { + component_state: 'STATE' + }; + + expect(decommissionable.getDecommissionStatusSuccessCallback(response)).to.eql(statusObject); + expect(decommissionable.setDecommissionStatus.calledWith(statusObject)).to.be.true; + }); + }); + + describe("#setStatusAs()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, 'startBlinking'); + }); + afterEach(function() { + decommissionable.startBlinking.restore(); + }); + + describe("#INSERVICE status", function() { + beforeEach(function() { + decommissionable.set('isStart', false); + decommissionable.setStatusAs('INSERVICE'); + }); + + it("isComponentRecommissionAvailable should be false", function() { + expect(decommissionable.get('isComponentRecommissionAvailable')).to.be.false; + }); + it("isComponentDecommissioning should be false", function() { + expect(decommissionable.get('isComponentDecommissioning')).to.be.false; + }); + it("isComponentDecommissionAvailable should be false", function() { + expect(decommissionable.get('isComponentDecommissionAvailable')).to.be.false; + }); + }); + + describe("#DECOMMISSIONING status", function() { + beforeEach(function() { + decommissionable.setStatusAs('DECOMMISSIONING') + }); + + it("isComponentRecommissionAvailable should be true", function() { + expect(decommissionable.get('isComponentRecommissionAvailable')).to.be.true; + }); + it("isComponentDecommissioning should be true", function() { + expect(decommissionable.get('isComponentDecommissioning')).to.be.true; + }); + it("isComponentDecommissionAvailable should be false", function() { + expect(decommissionable.get('isComponentDecommissionAvailable')).to.be.false; + }); + }); + + describe("#DECOMMISSIONED status", function() { + beforeEach(function() { + decommissionable.setStatusAs('DECOMMISSIONED') + }); + + it("isComponentRecommissionAvailable should be true", function() { + expect(decommissionable.get('isComponentRecommissionAvailable')).to.be.true; + }); + it("isComponentDecommissioning should be false", function() { + expect(decommissionable.get('isComponentDecommissioning')).to.be.false; + }); + it("isComponentDecommissionAvailable should be false", function() { + expect(decommissionable.get('isComponentDecommissionAvailable')).to.be.false; + }); + }); + + describe("#RS_DECOMMISSIONED status", function() { + beforeEach(function() { + decommissionable.set('isStart', false); + decommissionable.setStatusAs('RS_DECOMMISSIONED'); + }); + + it("isComponentRecommissionAvailable should be true", function() { + expect(decommissionable.get('isComponentRecommissionAvailable')).to.be.true; + }); + it("isComponentDecommissioning should be false", function() { + expect(decommissionable.get('isComponentDecommissioning')).to.be.false; + }); + it("isComponentDecommissionAvailable should be false", function() { + expect(decommissionable.get('isComponentDecommissionAvailable')).to.be.false; + }); + }); + }); + + + describe("#doBlinking()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, 'pulsate'); + sinon.spy(decommissionable, 'doBlinking'); + sinon.stub(decommissionable, 'startBlinking'); + }); + afterEach(function() { + decommissionable.pulsate.restore(); + decommissionable.doBlinking.restore(); + decommissionable.startBlinking.restore(); + }); + + it("INSTALLED status", function() { + decommissionable.setProperties({ + workStatus: 'INSTALLED', + content: Em.Object.create() + }); + decommissionable.doBlinking(); + expect(decommissionable.pulsate.called).to.be.false; + }); + + it("STARTED status, content is null", function() { + decommissionable.setProperties({ + workStatus: 'STARTED', + content: null + }); + decommissionable.doBlinking(); + expect(decommissionable.pulsate.called).to.be.false; + }); + + it("STARTED status, isDecommissioning = false", function() { + decommissionable.setProperties({ + workStatus: 'STARTED', + content: Em.Object.create(), + isDecommissioning: false + }); + decommissionable.doBlinking(); + expect(decommissionable.pulsate.called).to.be.false; + }); + + it("STARTED status, isDecommissioning = true, isBlinking = true", function() { + decommissionable.setProperties({ + workStatus: 'STARTED', + isDecommissioning: true, + isBlinking: true, + content: Em.Object.create() + }); + decommissionable.doBlinking(); + expect(decommissionable.pulsate.called).to.be.false; + }); + + it("STARTED status, isDecommissioning = true, isBlinking = false", function() { + decommissionable.setProperties({ + workStatus: 'STARTED', + isDecommissioning: true, + isBlinking: false, + content: Em.Object.create() + }); + decommissionable.doBlinking(); + expect(decommissionable.get('isBlinking')).to.be.true; + expect(decommissionable.pulsate.calledOnce).to.be.true; + }); + }); + + describe("#pulsate()", function() { + + beforeEach(function() { + sinon.stub(uiEffects, 'pulsate', function(node, time, callback) { + callback(); + }); + sinon.stub(decommissionable, 'doBlinking'); + decommissionable.pulsate(); + }); + afterEach(function() { + uiEffects.pulsate.restore(); + decommissionable.doBlinking.restore(); + }); + + it("uiEffects.pulsate should be called", function() { + expect(uiEffects.pulsate.calledOnce).to.be.true; + }); + + it("doBlinking should be called", function() { + expect(decommissionable.doBlinking.calledOnce).to.be.true; + }); + + it("isBlinking should be false", function() { + expect(decommissionable.get('isBlinking')).to.be.false; + }); + }); + + describe("#startBlinking()", function() { + + beforeEach(function() { + sinon.stub(decommissionable, '$').returns({stop: Em.K, css: Em.K}); + sinon.stub(decommissionable, 'doBlinking'); + }); + afterEach(function() { + decommissionable.$.restore(); + decommissionable.doBlinking.restore(); + }); + + it("doBlinking should be called", function() { + decommissionable.startBlinking(); + expect(decommissionable.doBlinking.calledOnce).to.be.true; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/mixins/main/host/details/host_components/install_component_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/mixins/main/host/details/host_components/install_component_test.js b/ambari-web/test/mixins/main/host/details/host_components/install_component_test.js new file mode 100644 index 0000000..a6aaa5b --- /dev/null +++ b/ambari-web/test/mixins/main/host/details/host_components/install_component_test.js @@ -0,0 +1,207 @@ +/** + * 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('mixins/main/host/details/host_components/install_component'); + +var installComponent; + +describe('App.InstallComponent', function () { + + beforeEach(function () { + installComponent = Em.Object.create(App.InstallComponent); + }); + + describe("#installHostComponentCall()", function() { + var component = Em.Object.create({ + componentName: 'C1', + displayName: 'c1' + }); + + beforeEach(function() { + sinon.stub(installComponent, 'updateAndCreateServiceComponent').returns({done: Em.clb}); + sinon.stub(App.ajax, 'send'); + installComponent.installHostComponentCall('host1', component); + }); + afterEach(function() { + installComponent.updateAndCreateServiceComponent.restore(); + App.ajax.send.restore(); + }); + + it("updateAndCreateServiceComponent should be called", function() { + expect(installComponent.updateAndCreateServiceComponent.calledWith('C1')).to.be.true; + }); + + it("App.ajax.send should be called", function() { + expect(App.ajax.send.getCall(0).args[0]).to.eql({ + name: 'host.host_component.add_new_component', + sender: installComponent, + data: { + hostName: 'host1', + component: component, + data: JSON.stringify({ + RequestInfo: { + "context": Em.I18n.t('requestInfo.installHostComponent') + " " + 'c1' + }, + Body: { + host_components: [ + { + HostRoles: { + component_name: 'C1' + } + } + ] + } + }) + }, + success: 'addNewComponentSuccessCallback', + error: 'ajaxErrorCallback' + }); + }); + }); + + describe("#addNewComponentSuccessCallback()", function() { + var params = { + hostName: 'host1', + component: Em.Object.create({ + componentName: 'C1', + serviceName: 'S1', + displayName: 'c1' + }) + }; + + beforeEach(function() { + sinon.stub(App.ajax, 'send'); + }); + afterEach(function() { + App.ajax.send.restore(); + }); + + + it("App.ajax.send should be called", function() { + installComponent.addNewComponentSuccessCallback({}, {}, params); + expect(App.ajax.send.getCall(0).args[0]).to.eql({ + name: 'common.host.host_component.update', + sender: App.router.get('mainHostDetailsController'), + data: { + hostName: 'host1', + componentName: 'C1', + serviceName: 'S1', + component: params.component, + "context": Em.I18n.t('requestInfo.installNewHostComponent') + " " + 'c1', + HostRoles: { + state: 'INSTALLED' + }, + urlParams: "HostRoles/state=INIT" + }, + success: 'installNewComponentSuccessCallback', + error: 'ajaxErrorCallback' + }); + }); + }); + + describe("#ajaxErrorCallback()", function() { + + beforeEach(function() { + sinon.stub(App.ajax, 'defaultErrorHandler'); + }); + afterEach(function() { + App.ajax.defaultErrorHandler.restore(); + }); + + it("App.ajax.defaultErrorHandler should be called", function() { + installComponent.ajaxErrorCallback({}, {}, 'error', {method: 'method1', url: 'url1'}, {}); + expect(App.ajax.defaultErrorHandler.calledWith({}, 'url1', 'method1')); + }); + }); + + describe("#updateAndCreateServiceComponent()", function() { + + var updater = { + updateComponentsState: Em.clb, + updateServiceMetric: Em.clb + }; + + beforeEach(function() { + sinon.spy(updater, 'updateComponentsState'); + sinon.spy(updater, 'updateServiceMetric'); + sinon.stub(App.router, 'get').returns(updater); + sinon.stub(installComponent, 'createServiceComponent'); + installComponent.updateAndCreateServiceComponent('C1'); + }); + afterEach(function() { + App.router.get.restore(); + installComponent.createServiceComponent.restore(); + updater.updateComponentsState.restore(); + updater.updateServiceMetric.restore(); + }); + + it("updater.updateComponentsState should be called", function() { + expect(updater.updateComponentsState.calledOnce).to.be.true; + }); + + it("updater.updateServiceMetric should be called", function() { + expect(updater.updateServiceMetric.calledOnce).to.be.true; + }); + + it("createServiceComponent should be called", function() { + expect(installComponent.createServiceComponent.calledWith('C1')).to.be.true; + }); + }); + + describe("#createServiceComponent()", function() { + var dfd = {resolve: Em.K}; + + beforeEach(function() { + sinon.stub(App.StackServiceComponent, 'find').returns([Em.Object.create({ + componentName: 'C2', + serviceName: 'S1' + })]); + sinon.spy(dfd, 'resolve'); + sinon.stub(App.ajax, 'send').returns({complete: Em.clb}); + this.mock = sinon.stub(App.Service, 'find'); + this.mock.returns([{serviceName: "S1"}]); + this.mock.withArgs('S1').returns(Em.Object.create({serviceComponents: ['C1']})) + + }); + afterEach(function() { + App.StackServiceComponent.find.restore(); + dfd.resolve.restore(); + this.mock.restore(); + App.ajax.send.restore(); + }); + + it("component already created", function() { + expect(installComponent.createServiceComponent('C1', dfd)).to.be.null; + expect(dfd.resolve.calledOnce).to.be.true; + }); + + it("component not created", function() { + installComponent.createServiceComponent('C2', dfd); + expect(App.ajax.send.getCall(0).args[0]).to.eql({ + name: 'common.create_component', + sender: installComponent, + data: { + componentName: 'C2', + serviceName: 'S1' + } + }); + expect(dfd.resolve.calledOnce).to.be.true; + }); + }); +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/views/main/alert_definitions_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alert_definitions_view_test.js b/ambari-web/test/views/main/alert_definitions_view_test.js index d4344c3..224cb7e 100644 --- a/ambari-web/test/views/main/alert_definitions_view_test.js +++ b/ambari-web/test/views/main/alert_definitions_view_test.js @@ -31,7 +31,7 @@ describe('App.MainAlertDefinitionsView', function () { beforeEach(function () { view = getView(); sinon.stub(App.db, 'setFilterConditions', Em.K); - sinon.stub(App.db, 'getFilterConditions', Em.K); + sinon.stub(App.db, 'getFilterConditions').returns([]); sinon.stub(App.db, 'getDisplayLength', Em.K); sinon.stub(App.db, 'setStartIndex', Em.K); sinon.stub(view, 'initFilters', Em.K); http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/views/main/alerts/definition_configs_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alerts/definition_configs_view_test.js b/ambari-web/test/views/main/alerts/definition_configs_view_test.js new file mode 100644 index 0000000..34f0acf --- /dev/null +++ b/ambari-web/test/views/main/alerts/definition_configs_view_test.js @@ -0,0 +1,123 @@ +/** + * 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 alertDefinitionConfigsView, alertConfigRadioButtonView; + +describe('App.AlertDefinitionConfigsView', function () { + + beforeEach(function () { + alertDefinitionConfigsView = App.AlertDefinitionConfigsView.create({ + controller: Em.Object.create({ + renderConfigs: Em.K + }) + }); + }); + + describe("#init()", function() { + + beforeEach(function() { + sinon.spy(alertDefinitionConfigsView.get('controller'), 'renderConfigs'); + alertDefinitionConfigsView.set('canEdit', true); + alertDefinitionConfigsView.set('isWizard', true); + alertDefinitionConfigsView.set('alertDefinitionType', 't1'); + alertDefinitionConfigsView.set('content', {}); + alertDefinitionConfigsView.init(); + }); + + afterEach(function() { + alertDefinitionConfigsView.get('controller').renderConfigs.restore(); + }); + + it("should set canEdit to controller", function() { + expect(alertDefinitionConfigsView.get('controller.canEdit')).to.be.true; + }); + + it("should set isWizard to controller", function() { + expect(alertDefinitionConfigsView.get('controller.isWizard')).to.be.true; + }); + + it("should set alertDefinitionType to controller", function() { + expect(alertDefinitionConfigsView.get('controller.alertDefinitionType')).to.equal('t1'); + }); + + it("should set content to controller", function() { + expect(alertDefinitionConfigsView.get('controller.content')).to.eql({}); + }); + + it("should call renderConfigs of controller", function() { + expect(alertDefinitionConfigsView.get('controller').renderConfigs.calledOnce).to.be.true; + }); + }); +}); + +describe('App.AlertConfigRadioButtonView', function () { + + beforeEach(function () { + alertConfigRadioButtonView = App.AlertConfigRadioButtonView.create({ + parentView: Em.Object.create({ + controller: Em.Object.create({ + changeType: Em.K, + configs: [ + Em.Object.create({ + group: 'g1', + value: true + }) + ] + }) + }), + property: { + name: 'p1' + } + }); + }); + + describe("#change", function() { + var config = Em.Object.create({ + group: 'g1', + value: true + }); + + beforeEach(function() { + sinon.stub(alertConfigRadioButtonView.get('parentView.controller'), 'changeType'); + alertConfigRadioButtonView.reopen({ + name: 'g1' + }); + alertConfigRadioButtonView.set('parentView.controller.configs', [config]); + alertConfigRadioButtonView.change(); + }); + + afterEach(function() { + alertConfigRadioButtonView.get('parentView.controller').changeType.restore(); + }); + + it("should set property.value", function() { + expect(alertConfigRadioButtonView.get('property.value')).to.be.true; + }); + + it("should set config value", function() { + expect(config.get('value')).to.be.false; + }); + + it("should call changeType()", function() { + expect(alertConfigRadioButtonView.get('parentView.controller').changeType.calledWith('p1')).to.be.true; + }); + }); + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/views/main/alerts/definition_details_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alerts/definition_details_view_test.js b/ambari-web/test/views/main/alerts/definition_details_view_test.js index 1358cb0..a3ed199 100644 --- a/ambari-web/test/views/main/alerts/definition_details_view_test.js +++ b/ambari-web/test/views/main/alerts/definition_details_view_test.js @@ -22,7 +22,12 @@ var view, instanceTableRow; function getView() { return App.MainAlertDefinitionDetailsView.create({ - initFilters: Em.K + initFilters: Em.K, + controller: Em.Object.create({ + loadAlertInstances: Em.K, + clearStep: Em.K, + content: Em.Object.create() + }) }); } @@ -30,43 +35,303 @@ describe('App.MainAlertDefinitionDetailsView', function () { beforeEach(function () { view = getView(); - instanceTableRow = view.get('instanceTableRow').create(); }); - describe("#goToHostAlerts()", function () { - beforeEach(function () { - sinon.stub(App.get('router'), 'transitionTo', Em.K); + describe("#willInsertElement()", function() { + + beforeEach(function() { + sinon.spy(view.get('controller'), 'clearStep'); + sinon.spy(view.get('controller'), 'loadAlertInstances'); + sinon.stub(view, 'loadDefinitionDetails'); }); - afterEach(function () { - App.get('router').transitionTo.restore(); + + afterEach(function() { + view.get('controller').clearStep.restore(); + view.get('controller').loadAlertInstances.restore(); + view.loadDefinitionDetails.restore(); + }); + + it("clearStep() should be called", function() { + view.willInsertElement(); + expect(view.get('controller').clearStep.calledOnce).to.be.true; + }); + + it("content is loaded", function() { + view.set('controller.content.isLoaded', true); + view.willInsertElement(); + expect(view.get('isLoaded')).to.be.true; + expect(view.get('controller').loadAlertInstances.calledOnce).to.be.true; + }); + + it("content is not loaded", function() { + view.set('controller.content.isLoaded', false); + view.willInsertElement(); + expect(view.get('isLoaded')).to.be.false; + expect(view.loadDefinitionDetails.calledOnce).to.be.true; + }); + }); + + describe("#loadDefinitionDetails()", function() { + var mock = { + updateAlertGroups: function(callback) { callback(); }, + updateAlertDefinitions: function(callback) { callback(); }, + updateAlertDefinitionSummary: function(callback) { callback(); } + }; + + beforeEach(function() { + sinon.stub(App.router, 'get').returns(mock); + sinon.spy(mock, 'updateAlertGroups'); + sinon.spy(mock, 'updateAlertDefinitions'); + sinon.spy(mock, 'updateAlertDefinitionSummary'); + sinon.stub(view.get('controller'), 'loadAlertInstances'); + sinon.stub(App.AlertDefinition, 'find').returns({}); + + view.loadDefinitionDetails(); }); - it("not route to host - no event", function () { - instanceTableRow.goToHostAlerts(null); - expect(App.get('router').transitionTo.notCalled).to.be.true; + + afterEach(function() { + App.router.get.restore(); + mock.updateAlertGroups.restore(); + mock.updateAlertDefinitions.restore(); + mock.updateAlertDefinitionSummary.restore(); + view.get('controller').loadAlertInstances.restore(); + App.AlertDefinition.find.restore(); }); - it("not route to host - no event context", function () { - instanceTableRow.goToHostAlerts({}); - expect(App.get('router').transitionTo.notCalled).to.be.true; + + it("updateAlertGroups() should be called", function() { + expect(mock.updateAlertGroups.calledOnce).to.be.true; + }); + + it("updateAlertDefinitions() should be called", function() { + expect(mock.updateAlertDefinitions.calledOnce).to.be.true; }); - it("routes to host", function () { - instanceTableRow.goToHostAlerts({"context": "hostname"}); - expect(App.get('router').transitionTo.calledOnce).to.be.true; + + it("updateAlertDefinitionSummary() should be called", function() { + expect(mock.updateAlertDefinitionSummary.calledOnce).to.be.true; + }); + + it("loadAlertInstances() should be called", function() { + expect(view.get('isLoaded')).to.be.true; + expect(view.get('controller.content')).to.eql({}); + expect(view.get('controller').loadAlertInstances.calledOnce).to.be.true; }); }); - describe("#openFullResponse()", function() { + describe("#didInsertElement()", function() { beforeEach(function() { - sinon.stub(App, 'showLogsPopup'); + sinon.stub(view, 'tooltipsUpdater'); + sinon.stub(view, 'filter'); }); afterEach(function() { - App.showLogsPopup.restore(); + view.tooltipsUpdater.restore(); + view.filter.restore(); + }); + + it("filter() should be called", function() { + view.didInsertElement(); + expect(view.filter.calledOnce).to.be.true; + }); + + it("tooltipsUpdater() should be called", function() { + view.didInsertElement(); + expect(view.tooltipsUpdater.calledOnce).to.be.true; + }); + }); + + describe("#tooltipsUpdater()", function () { + + beforeEach(function () { + sinon.stub(Em.run, 'next', Em.clb); + sinon.stub(App, 'tooltip'); + }); + + afterEach(function () { + Em.run.next.restore(); + App.tooltip.restore(); + }); + + it("Em.run.next should be called", function () { + view.tooltipsUpdater(); + expect(Em.run.next.calledOnce).to.be.true; + expect(App.tooltip.calledOnce).to.be.true; + }); + }); + + describe("#lastDayCount", function () { + var lastDayCountView; + + beforeEach(function () { + lastDayCountView = view.get('lastDayCount').create({ + hostName: 'host1', + parentView: Em.Object.create({ + controller: Em.Object.create() + }) + }); + }); + + describe("#count()", function () { + + it("lastDayAlertsCount is null", function () { + lastDayCountView.set('parentView.controller.lastDayAlertsCount', null); + expect(lastDayCountView.get('count')).to.equal(Em.I18n.t('app.loadingPlaceholder')); + }); + + it("lastDayAlertsCount does not contain host", function () { + lastDayCountView.set('parentView.controller.lastDayAlertsCount', {}); + expect(lastDayCountView.get('count')).to.equal(0); + }); + + it("lastDayAlertsCount is null", function () { + lastDayCountView.set('parentView.controller.lastDayAlertsCount', {host1: 1}); + expect(lastDayCountView.get('count')).to.equal(1); + }); + + }); + }); + + describe("#instanceTableRow", function() { + var instanceTableRowView; + + beforeEach(function () { + instanceTableRowView = view.get('instanceTableRow').create(); + }); + + describe("#didInsertElement()", function() { + + beforeEach(function() { + sinon.stub(App, 'tooltip'); + }); + afterEach(function() { + App.tooltip.restore(); + }); + + it("App.tooltip should be called", function() { + instanceTableRowView.didInsertElement(); + expect(App.tooltip.calledTwice).to.be.true; + }); + }); + + describe("#goToService()", function() { + + beforeEach(function() { + sinon.stub(App.router, 'transitionTo'); + }); + afterEach(function() { + App.router.transitionTo.restore(); + }); + + it("event is null", function() { + instanceTableRowView.goToService(null); + expect(App.router.transitionTo.called).to.be.false; + }); + + it("context is null", function() { + instanceTableRowView.goToService({context: null}); + expect(App.router.transitionTo.called).to.be.false; + }); + + it("correct context", function() { + instanceTableRowView.goToService({context: {}}); + expect(App.router.transitionTo.calledWith('main.services.service.summary', {})).to.be.true; + }); + }); + + describe("#goToHostAlerts()", function() { + var ctrl = Em.Object.create({ + referer: null + }); + + beforeEach(function() { + sinon.stub(App.router, 'transitionTo'); + sinon.stub(App.router, 'get').returns(ctrl); + }); + afterEach(function() { + App.router.transitionTo.restore(); + App.router.get.restore(); + }); + + it("event is null", function() { + instanceTableRowView.goToHostAlerts(null); + expect(App.router.transitionTo.called).to.be.false; + expect(ctrl.get('referer')).to.be.null; + }); + + it("context is null", function() { + instanceTableRowView.goToHostAlerts({context: null}); + expect(App.router.transitionTo.called).to.be.false; + expect(ctrl.get('referer')).to.be.null; + }); + + it("correct context", function() { + instanceTableRowView.goToHostAlerts({context: {}}); + expect(ctrl.get('referer')).to.equal('/login'); + expect(App.router.transitionTo.calledWith('main.hosts.hostDetails.alerts', {})).to.be.true; + }); + }); + describe("#openFullResponse()", function() { + + beforeEach(function() { + sinon.stub(App, 'showLogsPopup'); + }); + + afterEach(function() { + App.showLogsPopup.restore(); + }); + + it("App.showLogsPopup should be called", function() { + instanceTableRowView.openFullResponse({context: Em.Object.create({text: 'text1'})}); + expect(App.showLogsPopup.calledWith(Em.I18n.t('alerts.instance.fullLogPopup.header'), 'text1')).to.be.true; + }); + }); + }); + + + + describe("#paginationLeftClass", function() { + + it("startIndex is 2", function() { + view.set('startIndex', 2); + expect(view.get('paginationLeftClass')).to.equal('paginate_previous'); + }); + + it("startIndex is 1", function() { + view.set('startIndex', 1); + expect(view.get('paginationLeftClass')).to.equal('paginate_disabled_previous'); + }); + + it("startIndex is 0", function() { + view.set('startIndex', 0); + expect(view.get('paginationLeftClass')).to.equal('paginate_disabled_previous'); + }); + }); + + describe("#paginationRightClass", function() { + + it("endIndex more than filteredCount", function() { + view.reopen({ + endIndex: 4, + filteredCount: 3 + }); + expect(view.get('paginationRightClass')).to.equal('paginate_disabled_next'); + }); + + it("endIndex equal to filteredCount", function() { + view.reopen({ + endIndex: 4, + filteredCount: 4 + }); + expect(view.get('paginationRightClass')).to.equal('paginate_disabled_next'); }); - it("App.showLogsPopup should be called", function() { - instanceTableRow.openFullResponse({context: Em.Object.create({text: 'text1'})}); - expect(App.showLogsPopup.calledWith(Em.I18n.t('alerts.instance.fullLogPopup.header'), 'text1')).to.be.true; + it("endIndex less than filteredCount", function() { + view.reopen({ + endIndex: 3, + filteredCount: 4 + }); + view.propertyDidChange('paginationRightClass'); + expect(view.get('paginationRightClass')).to.equal('paginate_next'); }); }); @@ -78,6 +343,38 @@ function getInstanceView() { describe('App.AlertInstanceServiceHostView', function () { + var instanceView; + + beforeEach(function() { + instanceView = getInstanceView(); + }); + App.TestAliases.testAsComputedAnd(getInstanceView(), 'showSeparator', ['instance.serviceDisplayName', 'instance.hostName']); + describe("#serviceIsLink", function() { + + beforeEach(function() { + sinon.stub(App, 'get').returns(['S1']); + }); + afterEach(function() { + App.get.restore(); + }); + + it("service belongs to all", function() { + instanceView.set('instance', Em.Object.create({ + service: Em.Object.create({ + serviceName: 'S1' + }) + })); + expect(instanceView.get('serviceIsLink')).to.be.true; + }); + it("service does not belong to all", function() { + instanceView.set('instance', Em.Object.create({ + service: Em.Object.create({ + serviceName: 'S2' + }) + })); + expect(instanceView.get('serviceIsLink')).to.be.false; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/views/main/alerts/manage_alert_groups_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alerts/manage_alert_groups_view_test.js b/ambari-web/test/views/main/alerts/manage_alert_groups_view_test.js index 64e5c84..0ac4bde 100644 --- a/ambari-web/test/views/main/alerts/manage_alert_groups_view_test.js +++ b/ambari-web/test/views/main/alerts/manage_alert_groups_view_test.js @@ -18,6 +18,8 @@ var App = require('app'); +var view; + function getView() { return App.MainAlertsManageAlertGroupView.create({ controller: Em.Object.create() @@ -26,6 +28,201 @@ function getView() { describe('App.MainAlertsManageAlertGroupView', function () { + beforeEach(function () { + view = getView(); + }); + App.TestAliases.testAsComputedIfThenElse(getView(), 'removeButtonTooltip', 'controller.isRemoveButtonDisabled', Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeButtonDisabled'), Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeButton')) + + describe("#onGroupSelect()", function() { + + beforeEach(function() { + view.removeObserver('selectedAlertGroup', view, 'onGroupSelect'); + view.set('controller', Em.Object.create({selectedAlertGroup: null})); + }); + + it("selectedAlertGroup is null", function() { + view.set('selectedAlertGroup', null); + view.onGroupSelect(); + expect(view.get('selectedAlertGroup')).to.be.null; + expect(view.get('controller.selectedAlertGroup')).to.be.null; + expect(view.get('controller.selectedDefinitions')).to.be.empty; + }); + + it("selectedAlertGroup is empty array", function() { + view.set('selectedAlertGroup', []); + view.onGroupSelect(); + expect(view.get('selectedAlertGroup')).to.be.empty; + expect(view.get('controller.selectedAlertGroup')).to.be.null; + expect(view.get('controller.selectedDefinitions')).to.be.empty; + }); + + it("selectedAlertGroup is array with single element", function() { + view.set('selectedAlertGroup', [1]); + view.onGroupSelect(); + expect(view.get('selectedAlertGroup')).to.eql([1]); + expect(view.get('controller.selectedAlertGroup')).to.equal(1); + expect(view.get('controller.selectedDefinitions')).to.be.empty; + }); + + it("selectedAlertGroup is array with two elements", function() { + view.set('selectedAlertGroup', [1, 2]); + view.onGroupSelect(); + expect(view.get('selectedAlertGroup')).to.equal(2); + expect(view.get('controller.selectedAlertGroup')).to.equal(2); + expect(view.get('controller.selectedDefinitions')).to.be.empty; + }); + }); + + describe("#setGroupInController()", function() { + + beforeEach(function() { + view.removeObserver('controller.selectedAlertGroup', view, 'setGroupInController'); + view.set('controller', Em.Object.create({selectedAlertGroup: 1})); + view.set('selectedAlertGroup', null); + sinon.stub(view, 'onGroupSelect'); + }); + + afterEach(function() { + view.onGroupSelect.restore(); + }); + + it("controller.isLoaded is false", function() { + view.set('controller.isLoaded', false); + view.setGroupInController(); + expect(view.get('selectedAlertGroup')).to.be.null; + }); + + it("controller.isLoaded is true", function() { + view.set('controller.isLoaded', true); + view.setGroupInController(); + expect(view.get('selectedAlertGroup')).to.eql([1]); + }); + }); + + describe("#onLoad()", function() { + + beforeEach(function() { + view.removeObserver('controller.isLoaded', view, 'onLoad'); + view.set('controller', Em.Object.create({alertGroups: Em.A([{}])})); + view.set('selectedAlertGroup', null); + sinon.stub(view, 'setTooltips'); + }); + + afterEach(function() { + view.setTooltips.restore(); + }); + + it("controller.isLoaded is false", function() { + view.set('controller.isLoaded', false); + view.onLoad(); + expect(view.get('selectedAlertGroup')).to.be.null; + expect(view.setTooltips.called).to.be.false; + }); + + it("controller.isLoaded is true", function() { + view.set('controller.isLoaded', true); + view.onLoad(); + expect(view.get('selectedAlertGroup')).to.eql([{}]); + expect(view.setTooltips.calledOnce).to.be.true; + }); + }); + + describe("#willInsertElement()", function() { + + beforeEach(function() { + view.set('controller', Em.Object.create({loadAlertNotifications: Em.K})); + sinon.spy(view.get('controller'), 'loadAlertNotifications'); + }); + afterEach(function() { + view.get('controller').loadAlertNotifications.restore(); + }); + + it("loadAlertNotifications should be called", function() { + view.willInsertElement(); + expect(view.get('controller').loadAlertNotifications.calledOnce).to.be.true; + }); + }); + + describe("#didInsertElement()", function() { + + beforeEach(function() { + sinon.stub(view, 'onLoad'); + }); + afterEach(function() { + view.onLoad.restore(); + }); + + it("loadAlertNotifications should be called", function() { + view.didInsertElement(); + expect(view.onLoad.calledOnce).to.be.true; + }); + }); + + describe("#setTooltips()", function() { + + beforeEach(function() { + sinon.stub(Em.run, 'next', Em.clb); + sinon.stub(App, 'tooltip'); + view.setTooltips(); + }); + afterEach(function() { + Em.run.next.restore(); + App.tooltip.restore(); + }); + + it("Em.run.next should be called", function() { + expect(Em.run.next.calledOnce).to.be.true; + }); + + it("App.tooltip should be called twice", function() { + expect(App.tooltip.calledTwice).to.be.true; + }); + }); + + describe("#addDefinitionTooltip", function() { + + beforeEach(function() { + view.set('controller', Em.Object.create({selectedAlertGroup: Em.Object.create()})); + }); + + it("controller.selectedAlertGroup.default is true", function() { + view.set('controller.selectedAlertGroup.default', true); + expect(view.get('addDefinitionTooltip')).to.equal(Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinitionToDefault')); + }); + + it("controller.selectedAlertGroup.isAddDefinitionsDisabled is true", function() { + view.set('controller.selectedAlertGroup.isAddDefinitionsDisabled', true); + expect(view.get('addDefinitionTooltip')).to.equal(Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinitionDisabled')); + }); + + it("controller.selectedAlertGroup is null", function() { + view.set('controller.selectedAlertGroup', null); + expect(view.get('addDefinitionTooltip')).to.equal(Em.I18n.t('alerts.actions.manage_alert_groups_popup.addDefinition')); + }); + }); + + describe("#removeDefinitionTooltip", function() { + + beforeEach(function() { + view.set('controller', Em.Object.create({selectedAlertGroup: Em.Object.create()})); + }); + + it("controller.selectedAlertGroup.default is true", function() { + view.set('controller.selectedAlertGroup.default', true); + expect(view.get('removeDefinitionTooltip')).to.equal(Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeDefinitionDisabled')); + }); + + it("controller.isDeleteDefinitionsDisabled is true", function() { + view.set('controller.isDeleteDefinitionsDisabled', true); + expect(view.get('removeDefinitionTooltip')).to.equal(Em.I18n.t('common.nothingToDelete')); + }); + + it("isDeleteDefinitionsDisabled & selectedAlertGroup.default are false", function() { + view.set('controller.selectedAlertGroup.default', false); + view.set('controller.isDeleteDefinitionsDisabled', false); + expect(view.get('removeDefinitionTooltip')).to.equal(Em.I18n.t('alerts.actions.manage_alert_groups_popup.removeDefinition')); + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/ce192a48/ambari-web/test/views/main/alerts/manage_alert_notifications_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/alerts/manage_alert_notifications_view_test.js b/ambari-web/test/views/main/alerts/manage_alert_notifications_view_test.js index eb68f2f..43c05ad 100644 --- a/ambari-web/test/views/main/alerts/manage_alert_notifications_view_test.js +++ b/ambari-web/test/views/main/alerts/manage_alert_notifications_view_test.js @@ -34,7 +34,7 @@ describe('App.ManageAlertNotificationsView', function () { Em.A([ { - isOperator: false, + isOperator: false, selectedAlertNotification: {id: 1}, m: 'some alert notification is selected and user is an admin', p: { @@ -43,7 +43,7 @@ describe('App.ManageAlertNotificationsView', function () { isRemoveButtonDisabled: true, isDuplicateButtonDisabled: true }, - e: { + e: { isAddButtonDisabled: false, isEditButtonDisabled: false, isRemoveButtonDisabled: false, @@ -60,7 +60,7 @@ describe('App.ManageAlertNotificationsView', function () { isRemoveButtonDisabled: true, isDuplicateButtonDisabled: true }, - e: { + e: { isAddButtonDisabled: true, isEditButtonDisabled: true, isRemoveButtonDisabled: true, @@ -77,7 +77,7 @@ describe('App.ManageAlertNotificationsView', function () { isRemoveButtonDisabled: false, isDuplicateButtonDisabled: false }, - e: { + e: { isAddButtonDisabled: true, isEditButtonDisabled: true, isRemoveButtonDisabled: true, @@ -86,7 +86,7 @@ describe('App.ManageAlertNotificationsView', function () { }, { isOperator: true, - selectedAlertNotification: null, + selectedAlertNotification: null, m: 'some alert notification is not selected and user is a non-admin operator', p: { isAddButtonDisabled: true, @@ -94,7 +94,7 @@ describe('App.ManageAlertNotificationsView', function () { isRemoveButtonDisabled: false, isDuplicateButtonDisabled: false }, - e: { + e: { isAddButtonDisabled: true, isEditButtonDisabled: true, isRemoveButtonDisabled: true, @@ -102,18 +102,18 @@ describe('App.ManageAlertNotificationsView', function () { } } ]).forEach(function (test) { - it(test.m, function () { - Em.keys(test.p).forEach(function (k) { - view.set(k, test.p[k]); - }); - view.set('controller.selectedAlertNotification', test.selectedAlertNotification); - App.isOperator=test.isOperator; - view.buttonObserver(); - Em.keys(test.e).forEach(function (k) { - expect(view.get(k)).to.equal(test.e[k]); - }); + it(test.m, function () { + Em.keys(test.p).forEach(function (k) { + view.set(k, test.p[k]); + }); + view.set('controller.selectedAlertNotification', test.selectedAlertNotification); + App.isOperator = test.isOperator; + view.buttonObserver(); + Em.keys(test.e).forEach(function (k) { + expect(view.get(k)).to.equal(test.e[k]); }); }); + }); }); @@ -129,32 +129,233 @@ describe('App.ManageAlertNotificationsView', function () { e: true } ]).forEach(function (test, i) { - it('test ' + (i + 1), function () { - view.set('controller.selectedAlertNotification', test.selectedAlertNotification); - expect(view.get('showEmailDetails')).to.equal(test.e); - }); + it('test ' + (i + 1), function () { + view.set('controller.selectedAlertNotification', test.selectedAlertNotification); + expect(view.get('showEmailDetails')).to.equal(test.e); }); + }); }); describe('#showSNMPDetails', function () { Em.A([ - { - selectedAlertNotification: {type: 'SNMP'}, - e: true - }, - { - selectedAlertNotification: {type: 'EMAIL'}, - e: false - } - ]).forEach(function (test, i) { - it('test ' + (i + 1), function () { - view.set('controller.selectedAlertNotification', test.selectedAlertNotification); - expect(view.get('showSNMPDetails')).to.equal(test.e); - }); + { + selectedAlertNotification: {type: 'SNMP'}, + e: true + }, + { + selectedAlertNotification: {type: 'EMAIL'}, + e: false + } + ]).forEach(function (test, i) { + it('test ' + (i + 1), function () { + view.set('controller.selectedAlertNotification', test.selectedAlertNotification); + expect(view.get('showSNMPDetails')).to.equal(test.e); }); + }); + + }); + + describe("#selectedAlertNotificationGroups", function () { + it("should contain group names", function () { + view.set('controller', Em.Object.create({ + selectedAlertNotification: Em.Object.create({ + groups: [ + Em.Object.create({ + displayName: 'g1' + }), + Em.Object.create({ + displayName: 'g2' + }) + ] + }) + })); + expect(view.get('selectedAlertNotificationGroups')).to.equal('g1, g2'); + }); + }); + + describe("#email", function () { + it("should return ambari.dispatch.recipients", function () { + view.set('controller', Em.Object.create({ + selectedAlertNotification: Em.Object.create({ + properties: { + 'ambari.dispatch.recipients': 1 + } + }) + })); + expect(view.get('email')).to.equal(1); + }); + }); + + describe("#severities", function () { + it("should return list of states", function () { + view.set('controller', Em.Object.create({ + selectedAlertNotification: Em.Object.create({ + alertStates: ['st1', 'st2'] + }) + })); + expect(view.get('severities')).to.equal('st1, st2'); + }); + }); + + describe("#onAlertNotificationSelect()", function () { + + beforeEach(function () { + view.removeObserver('selectedAlertNotification', view, 'onAlertNotificationSelect'); + view.set('controller', Em.Object.create({selectedAlertNotification: null})); + }); + it("selectedAlertNotification is null", function () { + view.set('selectedAlertNotification', null); + view.onAlertNotificationSelect(); + expect(view.get('selectedAlertNotification')).to.be.null; + expect(view.get('controller.selectedAlertNotification')).to.be.null; + }); + + it("selectedAlertNotification is empty array", function () { + view.set('selectedAlertNotification', []); + view.onAlertNotificationSelect(); + expect(view.get('selectedAlertNotification')).to.be.empty; + expect(view.get('controller.selectedAlertNotification')).to.be.null; + }); + + it("selectedAlertNotification is array with single element", function () { + view.set('selectedAlertNotification', [1]); + view.onAlertNotificationSelect(); + expect(view.get('selectedAlertNotification')).to.eql([1]); + expect(view.get('controller.selectedAlertNotification')).to.equal(1); + }); + + it("selectedAlertNotification is array with two elements", function () { + view.set('selectedAlertNotification', [1, 2]); + view.onAlertNotificationSelect(); + expect(view.get('selectedAlertNotification')).to.equal(2); + expect(view.get('controller.selectedAlertNotification')).to.equal(2); + }); }); + describe("#willInsertElement()", function () { + + beforeEach(function () { + view.set('controller', Em.Object.create({loadAlertNotifications: Em.K})); + sinon.spy(view.get('controller'), 'loadAlertNotifications'); + }); + afterEach(function () { + view.get('controller').loadAlertNotifications.restore(); + }); + + it("loadAlertNotifications should be called", function () { + view.willInsertElement(); + expect(view.get('controller').loadAlertNotifications.calledOnce).to.be.true; + }); + }); + + describe("#didInsertElement()", function () { + + beforeEach(function () { + sinon.stub(view, 'onLoad'); + }); + afterEach(function () { + view.onLoad.restore(); + }); + + it("loadAlertNotifications should be called", function () { + view.didInsertElement(); + expect(view.onLoad.calledOnce).to.be.true; + }); + }); + + describe("#onLoad()", function () { + + beforeEach(function () { + view.removeObserver('controller.isLoaded', view, 'onLoad'); + view.set('controller', Em.Object.create()); + sinon.stub(view, 'buttonObserver'); + sinon.stub(Em.run, 'later', function (context, callback) { + callback(); + }); + sinon.stub(App, 'tooltip'); + this.clock = sinon.useFakeTimers(); + }); + afterEach(function () { + view.buttonObserver.restore(); + Em.run.later.restore(); + App.tooltip.restore(); + this.clock.restore(); + }); + + it("controller.isLoaded is false", function () { + view.set('controller.isLoaded', false); + view.onLoad(); + expect(Em.run.later.called).to.be.false; + }); + + describe("controller.isLoaded is true, alertNotifications is null", function () { + + beforeEach(function () { + view.set('controller.isLoaded', true); + view.set('controller.alertNotifications', null); + }); + + it("Em.run.later should be called", function () { + view.onLoad(); + expect(Em.run.later.calledOnce).to.be.true; + }); + + it("App.tooltip should be called twice", function () { + view.onLoad(); + this.clock.tick(50); + expect(App.tooltip.calledTwice).to.be.true; + }); + + it("selectedAlertNotification should be null", function () { + view.onLoad(); + expect(view.get('selectedAlertNotification')).to.be.null; + }); + + it("isAddButtonDisabled should be true", function () { + view.set('isAddButtonDisabled', true); + App.isOperator = true; + view.onLoad(); + expect(view.get('isAddButtonDisabled')).to.be.true; + }); + + it("isAddButtonDisabled should be false", function () { + view.set('isAddButtonDisabled', true); + App.isOperator = false; + view.onLoad(); + expect(view.get('isAddButtonDisabled')).to.be.false; + }); + }); + + describe("controller.isLoaded is true, alertNotifications is array", function () { + + beforeEach(function () { + view.set('controller.isLoaded', true); + view.set('controller.alertNotifications', [{}]); + }); + + it("Em.run.later should be called", function () { + view.onLoad(); + expect(Em.run.later.calledOnce).to.be.true; + }); + + it("App.tooltip should be called twice", function () { + view.onLoad(); + this.clock.tick(50); + expect(App.tooltip.calledTwice).to.be.true; + }); + + it("selectedAlertNotification should be object", function () { + view.onLoad(); + expect(view.get('selectedAlertNotification')).to.eql({}); + }); + + it("buttonObserver should be called", function () { + view.onLoad(); + expect(view.buttonObserver.calledOnce).to.be.true; + }); + }); + }); });
