You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ja...@apache.org on 2016/07/21 21:02:22 UTC
[07/19] ambari git commit: AMBARI-17813 Cover configurations mixin
with unit tests. (atkach)
AMBARI-17813 Cover configurations mixin 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/07b42367
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/07b42367
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/07b42367
Branch: refs/heads/branch-embedded-views
Commit: 07b423677ab3ab87debffdb732b5d95a7f9ae13c
Parents: 7acc909
Author: Andrii Tkach <at...@apache.org>
Authored: Wed Jul 20 18:23:18 2016 +0300
Committer: Andrii Tkach <at...@apache.org>
Committed: Thu Jul 21 14:09:11 2016 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 1 +
.../configs/component_actions_by_configs.js | 149 +++---
.../main/service/configs/config_overridable.js | 143 +++--
.../service/configs/widget_popover_support.js | 2 +-
.../component_actions_by_configs_test.js | 519 +++++++++++++++++++
.../service/configs/config_overridable_test.js | 357 ++++++++++++-
.../configs/widget_popover_support_test.js | 165 +++++-
7 files changed, 1212 insertions(+), 124 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/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 2b73b39..0bd8c2d 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -168,6 +168,7 @@ var files = [
'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/main/service/configs/component_actions_by_configs_test',
'test/mixins/routers/redirections_test',
'test/mixins/wizard/addSeccurityConfigs_test',
'test/mixins/wizard/assign_master_components_test',
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js b/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js
index 9271675..c7bb047 100644
--- a/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js
+++ b/ambari-web/app/mixins/main/service/configs/component_actions_by_configs.js
@@ -31,7 +31,7 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @public
* @method doConfigActions
*/
- doConfigActions: function() {
+ doConfigActions: function () {
var serviceConfigs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
var configActionComponents = serviceConfigs.filterProperty('configActionComponent');
this.doComponentDeleteActions(configActionComponents);
@@ -44,7 +44,7 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @public
* @method isComponentActionsPresent
*/
- isComponentActionsPresent: function() {
+ isComponentActionsPresent: function () {
var serviceConfigs = this.get('stepConfigs').findProperty('serviceName', this.get('content.serviceName')).get('configs');
var configActionComponents = serviceConfigs.filterProperty('configActionComponent');
return !!(this.getComponentsToDelete(configActionComponents).length + this.getComponentsToAdd(configActionComponents).length);
@@ -57,11 +57,13 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method getComponentsToDelete
*/
- getComponentsToDelete: function(configActionComponents) {
- return configActionComponents.filterProperty('configActionComponent.action', 'delete').map(function(item){
+ getComponentsToDelete: function (configActionComponents) {
+ var hostComponents = App.HostComponent.find();
+ return configActionComponents.filterProperty('configActionComponent.action', 'delete').map(function (item) {
return item.configActionComponent;
- }).filter(function(_componentToDelete){
- return App.HostComponent.find().filterProperty('componentName',_componentToDelete.componentName).someProperty('hostName', _componentToDelete.hostName);
+ }).filter(function (_componentToDelete) {
+ return hostComponents.filterProperty('componentName', _componentToDelete.componentName)
+ .someProperty('hostName', _componentToDelete.hostName);
}, this);
},
@@ -72,15 +74,17 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method getComponentsToDelete
*/
- getComponentsToAdd: function(configActionComponents) {
- return configActionComponents.filterProperty('configActionComponent.action', 'add').map(function(item){
+ getComponentsToAdd: function (configActionComponents) {
+ var ssc = App.StackServiceComponent.find(),
+ services = App.Service.find();
+ return configActionComponents.filterProperty('configActionComponent.action', 'add').map(function (item) {
return item.configActionComponent;
- }).filter(function(_componentToAdd) {
- var serviceNameForcomponent = App.StackServiceComponent.find().findProperty('componentName',_componentToAdd.componentName).get('serviceName');
+ }).filter(function (_componentToAdd) {
+ var serviceNameForcomponent = ssc.findProperty('componentName', _componentToAdd.componentName).get('serviceName');
// List of host components to be added should not include ones that are already present in the cluster.
// Need to do below check from App.Service model as it keeps getting polled and updated on service page.
- return !App.Service.find().findProperty('serviceName', serviceNameForcomponent).get('hostComponents').
- filterProperty('componentName',_componentToAdd.componentName).someProperty('hostName', _componentToAdd.hostName);
+ return !services.findProperty('serviceName', serviceNameForcomponent).get('hostComponents').
+ filterProperty('componentName', _componentToAdd.componentName).someProperty('hostName', _componentToAdd.hostName);
}, this);
},
@@ -90,16 +94,16 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method {configActionComponents}
*/
- doComponentDeleteActions: function(configActionComponents) {
+ doComponentDeleteActions: function (configActionComponents) {
var componentsToDelete = this.getComponentsToDelete(configActionComponents);
if (componentsToDelete.length) {
// There is always only one item to delete when doing config actions.
- var componentToDelete = componentsToDelete[0];
+ var componentToDelete = componentsToDelete[0];
var componentName = componentToDelete.componentName;
var hostName = componentToDelete.hostName;
- var displayName = App.StackServiceComponent.find().findProperty('componentName', componentToDelete.componentName).get('displayName');
+ var displayName = App.StackServiceComponent.find().findProperty('componentName', componentToDelete.componentName).get('displayName');
var context = Em.I18n.t('requestInfo.stop').format(displayName);
- var batches =[];
+ var batches = [];
this.setRefreshYarnQueueRequest(batches);
batches.push(this.getInstallHostComponentsRequest(hostName, componentName, context));
@@ -124,37 +128,23 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method {doComponentAddActions}
*/
- doComponentAddActions: function(configActionComponents) {
- var self = this;
+ doComponentAddActions: function (configActionComponents) {
var componentsToAdd = this.getComponentsToAdd(configActionComponents);
- var dependentComponents = [];
+
if (componentsToAdd.length) {
- componentsToAdd.forEach(function(_component) {
- var dependencies = App.StackServiceComponent.find(_component.componentName).get('dependencies').filterProperty('scope', 'host').map(function(_dependency){
- return {
- componentName: _dependency.componentName,
- hostName: _component.hostName,
- isClient: App.StackServiceComponent.find(_dependency.componentName).get('isClient')
- }
- }, this);
- var dependenciesToInstall = dependencies.filter(function (_dependencyToAdd) {
- var isInstalled = App.HostComponent.find().filterProperty('componentName', _dependencyToAdd.componentName).someProperty('hostName', _dependencyToAdd.hostName);
- var isAddedToInstall = dependentComponents.filterProperty('componentName',_dependencyToAdd.componentName).someProperty('hostName', _dependencyToAdd.hostName);
- return !(isInstalled || isAddedToInstall);
- }, this);
- dependentComponents = dependentComponents.concat(dependenciesToInstall);
- }, this);
- var allComponentsToAdd = componentsToAdd.concat(dependentComponents);
+ var allComponentsToAdd = componentsToAdd.concat(this.getDependentComponents(componentsToAdd));
var allComponentsToAddHosts = allComponentsToAdd.mapProperty('hostName').uniq();
- allComponentsToAddHosts.forEach(function(_hostName){
+
+ allComponentsToAddHosts.forEach(function (_hostName) {
var hostComponents = allComponentsToAdd.filterProperty('hostName', _hostName).mapProperty('componentName').uniq();
- var masterHostComponents = allComponentsToAdd.filterProperty('hostName', _hostName).filterProperty('isClient', false).mapProperty('componentName').uniq();
- var displayNames = masterHostComponents.map(function(item) {
+ var masterHostComponents = allComponentsToAdd.filterProperty('hostName', _hostName).filterProperty('isClient', false).mapProperty('componentName').uniq();
+ var displayNames = masterHostComponents.map(function (item) {
return App.StackServiceComponent.find().findProperty('componentName', item).get('displayName');
});
- var displayStr = stringUtils.getFormattedStringFromArray(displayNames);
+
+ var displayStr = stringUtils.getFormattedStringFromArray(displayNames);
var context = Em.I18n.t('requestInfo.start').format(displayStr);
- var batches =[];
+ var batches = [];
this.setCreateComponentRequest(batches, hostComponents);
batches.push(this.getCreateHostComponentsRequest(_hostName, hostComponents));
batches.push(this.getInstallHostComponentsRequest(_hostName, hostComponents));
@@ -176,13 +166,39 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
},
/**
+ * @method getDependentComponents
+ * @param {Array} componentsToAdd
+ * @returns {Array}
+ */
+ getDependentComponents: function(componentsToAdd) {
+ var dependentComponents = [];
+
+ componentsToAdd.forEach(function (_component) {
+ var dependencies = App.StackServiceComponent.find(_component.componentName).get('dependencies').filterProperty('scope', 'host').map(function (_dependency) {
+ return {
+ componentName: _dependency.componentName,
+ hostName: _component.hostName,
+ isClient: App.StackServiceComponent.find(_dependency.componentName).get('isClient')
+ }
+ }, this);
+ var dependenciesToInstall = dependencies.filter(function (_dependencyToAdd) {
+ var isInstalled = App.HostComponent.find().filterProperty('componentName', _dependencyToAdd.componentName).someProperty('hostName', _dependencyToAdd.hostName);
+ var isAddedToInstall = dependentComponents.filterProperty('componentName', _dependencyToAdd.componentName).someProperty('hostName', _dependencyToAdd.hostName);
+ return !(isInstalled || isAddedToInstall);
+ }, this);
+ dependentComponents = dependentComponents.concat(dependenciesToInstall);
+ }, this);
+ return dependentComponents;
+ },
+
+ /**
* Sets order_id for each batch request in the `batches` array
* @param batches {Array}
* @private
* @method {setOrderIdForBatches}
*/
- setOrderIdForBatches: function(batches) {
- batches.forEach(function(_batch, index){
+ setOrderIdForBatches: function (batches) {
+ batches.forEach(function (_batch, index) {
_batch.order_id = index + 1;
}, this);
},
@@ -193,18 +209,18 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @param components {String[]}|{String}
* @return {Object} Deferred promise
*/
- getCreateHostComponentsRequest: function(hostName, components) {
- var query = "Hosts/host_name.in(" + hostName + ")";
+ getCreateHostComponentsRequest: function (hostName, components) {
+ var query = "Hosts/host_name.in(" + hostName + ")";
components = (Array.isArray(components)) ? components : [components];
- var hostComponent = components.map(function(_componentName){
+ var hostComponent = components.map(function (_componentName) {
return {
- "HostRoles":{
- "component_name":_componentName
+ "HostRoles": {
+ "component_name": _componentName
}
}
}, this);
- return {
+ return {
"type": 'POST',
"uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/hosts",
"RequestBodyInfo": {
@@ -225,7 +241,7 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @param context {String} Optional
* @return {Object}
*/
- getInstallHostComponentsRequest: function(hostName, components, context) {
+ getInstallHostComponentsRequest: function (hostName, components, context) {
context = context || Em.I18n.t('requestInfo.installComponents');
return this.getUpdateHostComponentsRequest(hostName, components, App.HostComponentStatus.stopped, context);
},
@@ -237,7 +253,7 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @param context {String} Optional
* @return {Object}
*/
- getStartHostComponentsRequest: function(hostName, components, context) {
+ getStartHostComponentsRequest: function (hostName, components, context) {
context = context || Em.I18n.t('requestInfo.startHostComponents');
return this.getUpdateHostComponentsRequest(hostName, components, App.HostComponentStatus.started, context);
},
@@ -253,11 +269,11 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @method {getUpdateHostComponentsRequest}
* @return {Object}
*/
- getUpdateHostComponentsRequest: function(hostName, components, desiredState, context) {
+ getUpdateHostComponentsRequest: function (hostName, components, desiredState, context) {
components = (Array.isArray(components)) ? components : [components];
var query = "HostRoles/component_name.in(" + components.join(',') + ")";
- return {
+ return {
"type": 'PUT',
"uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components",
"RequestBodyInfo": {
@@ -287,7 +303,7 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @method {getDeleteHostComponentRequest}
* @return {Object}
*/
- getDeleteHostComponentRequest: function(hostName, component) {
+ getDeleteHostComponentRequest: function (hostName, component) {
return {
"type": 'DELETE',
"uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/hosts/" + hostName + "/host_components/" + component
@@ -301,10 +317,13 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method {setCreateComponentRequest}
*/
- setCreateComponentRequest: function(batches, hostComponents) {
- hostComponents.forEach(function(_componentName){
- var serviceName = App.StackServiceComponent.find().findProperty('componentName', _componentName).get('serviceName');
- var serviceComponents = App.Service.find().findProperty('serviceName', serviceName).get('serviceComponents');
+ setCreateComponentRequest: function (batches, hostComponents) {
+ var stackServices = App.StackServiceComponent.find(),
+ services = App.Service.find();
+
+ hostComponents.forEach(function (_componentName) {
+ var serviceName = stackServices.findProperty('componentName', _componentName).get('serviceName');
+ var serviceComponents = services.findProperty('serviceName', serviceName).get('serviceComponents');
if (!serviceComponents.contains(_componentName)) {
batches.push({
"type": 'POST',
@@ -320,25 +339,27 @@ App.ComponentActionsByConfigs = Em.Mixin.create({
* @private
* @method {setRefreshYarnQueueRequest}
*/
- setRefreshYarnQueueRequest: function(batches) {
- var capacitySchedulerConfigs = this.get('allConfigs').filterProperty('filename', 'capacity-scheduler.xml').filter(function(item){
+ setRefreshYarnQueueRequest: function (batches) {
+ var capacitySchedulerConfigs = this.get('allConfigs')
+ .filterProperty('filename', 'capacity-scheduler.xml')
+ .filter(function (item) {
return item.get('value') !== item.get('initialValue');
});
if (capacitySchedulerConfigs.length) {
var serviceName = 'YARN';
var componentName = 'RESOURCEMANAGER';
- var commandName = 'REFRESHQUEUES';
- var tag = 'capacity-scheduler';
- var hostNames = App.Service.find(serviceName).get('hostComponents').filterProperty('componentName', componentName).mapProperty('hostName');
+ var hostNames = App.Service.find(serviceName).get('hostComponents')
+ .filterProperty('componentName', componentName)
+ .mapProperty('hostName');
batches.push({
"type": 'POST',
"uri": App.get('apiPrefix') + "/clusters/" + App.get('clusterName') + "/requests",
"RequestBodyInfo": {
"RequestInfo": {
"context": Em.I18n.t('services.service.actions.run.yarnRefreshQueues.context'),
- "command": commandName,
- "parameters/forceRefreshConfigTags": tag
+ "command": "REFRESHQUEUES",
+ "parameters/forceRefreshConfigTags": "capacity-scheduler"
},
"Requests/resource_filters": [
{
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/app/mixins/main/service/configs/config_overridable.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/service/configs/config_overridable.js b/ambari-web/app/mixins/main/service/configs/config_overridable.js
index 920e5c4..a8bd273 100644
--- a/ambari-web/app/mixins/main/service/configs/config_overridable.js
+++ b/ambari-web/app/mixins/main/service/configs/config_overridable.js
@@ -63,7 +63,10 @@ App.ConfigOverridable = Em.Mixin.create({
}
else {
var valueForOverride = (serviceConfigProperty.get('widget') || serviceConfigProperty.get('displayType') == 'checkbox') ? serviceConfigProperty.get('value') : '';
- App.config.createOverride(serviceConfigProperty, { "value": valueForOverride, "isEditable": true }, selectedConfigGroup);
+ App.config.createOverride(serviceConfigProperty, {
+ "value": valueForOverride,
+ "isEditable": true
+ }, selectedConfigGroup);
}
Em.$('body>.tooltip').remove();
},
@@ -253,35 +256,45 @@ App.ConfigOverridable = Em.Mixin.create({
})
}
};
- var sendData = {
+ return App.ajax.send({
name: 'config_groups.create',
+ sender: this,
data: {
data: [newGroupData],
modelData: newConfigGroupData
},
- success: 'successFunction',
- error: 'errorFunction',
- successFunction: function (response, opt, params) {
- var modelData = params.modelData;
- modelData.id = response.resources[0].ConfigGroup.id;
- App.store.load(App.ServiceConfigGroup, modelData);
- App.store.commit();
- App.ServiceConfigGroup.deleteTemporaryRecords();
- if (callback) {
- callback();
- }
- },
- errorFunction: function (xhr, text, errorThrown) {
- if (callback) {
- callback(xhr, text, errorThrown);
- }
+ success: 'postNewConfigurationGroupSuccess',
+ error: 'postNewConfigurationGroupError'
+ }).always(function (xhr, text, errorThrown) {
+ if (callback) {
+ callback(xhr, text, errorThrown);
}
- };
- sendData.sender = sendData;
- return App.ajax.send(sendData);
+ });
},
/**
+ *
+ * @param {string} response
+ * @param {object} opt
+ * @param {object} params
+ */
+ postNewConfigurationGroupSuccess: function (response, opt, params) {
+ var modelData = params.modelData;
+ modelData.id = response.resources[0].ConfigGroup.id;
+ App.store.load(App.ServiceConfigGroup, modelData);
+ App.store.commit();
+ App.ServiceConfigGroup.deleteTemporaryRecords();
+ },
+
+ /**
+ *
+ * @param {object} xhr
+ * @param {string} text
+ * @param {Error} errorThrown
+ */
+ postNewConfigurationGroupError: Em.K,
+
+ /**
* PUTs the new configuration-group on the server.
* Changes possible here are the name, description and
* host memberships of the configuration-group.
@@ -293,31 +306,11 @@ App.ConfigOverridable = Em.Mixin.create({
* @method updateConfigurationGroup
*/
updateConfigurationGroup: function (configGroup, successCallback, errorCallback) {
- var desiredConfigs = configGroup.get('desiredConfigs') || [];
- var putConfigGroup = {
- ConfigGroup: {
- group_name: configGroup.get('name'),
- description: configGroup.get('description'),
- tag: configGroup.get('service.id'),
- hosts: configGroup.get('hosts').map(function (h) {
- return {
- host_name: h
- };
- }),
- desired_configs: desiredConfigs.map(function (cst) {
- return {
- type: Em.get(cst, 'site') || Em.get(cst, 'type'),
- tag: Em.get(cst, 'tag')
- };
- })
- }
- };
-
var sendData = {
name: 'config_groups.update',
data: {
id: configGroup.get('id'),
- data: putConfigGroup
+ data: this.getConfigGroupData(configGroup)
},
success: 'successFunction',
error: 'errorFunction',
@@ -337,6 +330,34 @@ App.ConfigOverridable = Em.Mixin.create({
},
/**
+ *
+ * @param {Em.Object} configGroup
+ * @returns {{ConfigGroup: {group_name: *, description: *, tag: *, hosts: *, desired_configs: (Array|*)}}}
+ */
+ getConfigGroupData: function (configGroup) {
+ var desiredConfigs = configGroup.get('desiredConfigs') || [];
+
+ return {
+ ConfigGroup: {
+ group_name: configGroup.get('name'),
+ description: configGroup.get('description'),
+ tag: configGroup.get('service.id'),
+ hosts: configGroup.get('hosts').map(function (h) {
+ return {
+ host_name: h
+ };
+ }),
+ desired_configs: desiredConfigs.map(function (cst) {
+ return {
+ type: Em.get(cst, 'site') || Em.get(cst, 'type'),
+ tag: Em.get(cst, 'tag')
+ };
+ })
+ }
+ };
+ },
+
+ /**
* launch dialog where can be assigned another group to host
* @param {App.ConfigGroup} selectedGroup
* @param {App.ConfigGroup[]} configGroups
@@ -391,6 +412,7 @@ App.ConfigOverridable = Em.Mixin.create({
* @method deleteConfigurationGroup
*/
deleteConfigurationGroup: function (configGroup, successCallback, errorCallback) {
+ var self = this;
var sendData = {
name: 'common.delete.config_group',
sender: this,
@@ -400,13 +422,7 @@ App.ConfigOverridable = Em.Mixin.create({
success: 'successFunction',
error: 'errorFunction',
successFunction: function (data, xhr, params) {
- var groupFromModel = App.ServiceConfigGroup.find().findProperty('id', params.id);
- if (groupFromModel) {
- if (groupFromModel.get('stateManager.currentState.name') !== 'saved') {
- groupFromModel.get('stateManager').transitionTo('loaded');
- }
- App.configGroupsMapper.deleteRecord(groupFromModel);
- }
+ self.deleteConfigurationGroupSuccess(data, xhr, params);
if (successCallback) {
successCallback();
}
@@ -421,6 +437,23 @@ App.ConfigOverridable = Em.Mixin.create({
return App.ajax.send(sendData);
},
+
+ /**
+ *
+ * @param {object} data
+ * @param {object} xhr
+ * @param {object} params
+ */
+ deleteConfigurationGroupSuccess: function (data, xhr, params) {
+ var groupFromModel = App.ServiceConfigGroup.find().findProperty('id', params.id);
+ if (groupFromModel) {
+ if (groupFromModel.get('stateManager.currentState.name') !== 'saved') {
+ groupFromModel.get('stateManager').transitionTo('loaded');
+ }
+ App.configGroupsMapper.deleteRecord(groupFromModel);
+ }
+ },
+
/**
* Launches a dialog where an existing config-group can be selected, or a new
* one can be created. This is different than the config-group management
@@ -444,11 +477,11 @@ App.ConfigOverridable = Em.Mixin.create({
bodyClass: Em.View.extend({
templateName: require('templates/common/configs/saveConfigGroup')
}),
- onPrimary:function() {
- if (self.get('controller.name') == 'mainServiceInfoConfigsController') {
- self.get('controller').loadConfigGroups([self.get('controller.content.serviceName')]).done(function() {
- var group = App.ServiceConfigGroup.find().find(function(g) {
- return g.get('serviceName') == self.get('controller.content.serviceName') && g.get('name') == groupName;
+ onPrimary: function () {
+ if (self.get('controller.name') === 'mainServiceInfoConfigsController') {
+ self.get('controller').loadConfigGroups([self.get('controller.content.serviceName')]).done(function () {
+ var group = App.ServiceConfigGroup.find().find(function (g) {
+ return g.get('serviceName') === self.get('controller.content.serviceName') && g.get('name') === groupName;
});
self.get('controller').doSelectConfigGroup({context: group});
});
@@ -469,7 +502,7 @@ App.ConfigOverridable = Em.Mixin.create({
persistConfigGroups: function () {
var installerController = App.router.get('installerController');
var step7Controller = App.router.get('wizardStep7Controller');
- installerController.saveServiceConfigGroups(step7Controller, step7Controller.get('content.controllerName') == 'addServiceController');
+ installerController.saveServiceConfigGroups(step7Controller, step7Controller.get('content.controllerName') === 'addServiceController');
App.clusterStatus.setClusterStatus({
localdb: App.db.data
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/app/mixins/main/service/configs/widget_popover_support.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/main/service/configs/widget_popover_support.js b/ambari-web/app/mixins/main/service/configs/widget_popover_support.js
index ded8dd9..dc9f7d3 100644
--- a/ambari-web/app/mixins/main/service/configs/widget_popover_support.js
+++ b/ambari-web/app/mixins/main/service/configs/widget_popover_support.js
@@ -44,7 +44,7 @@ App.WidgetPopoverSupport = Em.Mixin.create({
* @type {string}
*/
popoverPlacement: function () {
- return this.get('section.isLastColumn') && this.get('subSection.isLastColumn')? 'left' : 'right';
+ return this.get('section.isLastColumn') && this.get('subSection.isLastColumn') ? 'left' : 'right';
}.property('section.isLastColumn', 'subSection.isLastColumn'),
initPopover: function () {
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/test/mixins/main/service/configs/component_actions_by_configs_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/main/service/configs/component_actions_by_configs_test.js b/ambari-web/test/mixins/main/service/configs/component_actions_by_configs_test.js
new file mode 100644
index 0000000..a6877fe
--- /dev/null
+++ b/ambari-web/test/mixins/main/service/configs/component_actions_by_configs_test.js
@@ -0,0 +1,519 @@
+/**
+ * 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.
+ */
+
+require('mixins/main/service/configs/component_actions_by_configs');
+var testHelpers = require('test/helpers');
+var stringUtils = require('utils/string_utils');
+
+
+var mixin;
+
+describe('App.ComponentActionsByConfigs', function () {
+
+ beforeEach(function() {
+ mixin = Em.Object.create(App.ComponentActionsByConfigs, {
+ stepConfigs: [],
+ content: Em.Object.create()
+ });
+ });
+
+ describe("#doConfigActions()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'doComponentDeleteActions');
+ sinon.stub(mixin, 'doComponentAddActions');
+ mixin.set('stepConfigs', [Em.Object.create({
+ serviceName: 'S1',
+ configs: [{
+ configActionComponent: {}
+ }]
+ })]);
+ mixin.set('content.serviceName', 'S1');
+ mixin.doConfigActions();
+ });
+
+ afterEach(function() {
+ mixin.doComponentDeleteActions.restore();
+ mixin.doComponentAddActions.restore();
+ });
+
+ it("doComponentDeleteActions should be called", function() {
+ expect(mixin.doComponentDeleteActions.calledWith([{
+ configActionComponent: {}
+ }])).to.be.true;
+ });
+
+ it("doComponentAddActions should be called", function() {
+ expect(mixin.doComponentAddActions.calledWith([{
+ configActionComponent: {}
+ }])).to.be.true;
+ });
+ });
+
+ describe("#isComponentActionsPresent()", function () {
+
+ beforeEach(function() {
+ this.mockDelete = sinon.stub(mixin, 'getComponentsToDelete').returns(1);
+ this.mockAdd = sinon.stub(mixin, 'getComponentsToAdd').returns(1);
+ mixin.set('stepConfigs', [Em.Object.create({
+ serviceName: 'S1',
+ configs: [{
+ configActionComponent: {}
+ }]
+ })]);
+ mixin.set('content.serviceName', 'S1');
+ });
+
+ afterEach(function() {
+ this.mockAdd.restore();
+ this.mockDelete.restore();
+ });
+
+ it("no delete or add components", function() {
+ this.mockAdd.returns([]);
+ this.mockDelete.returns([]);
+ expect(mixin.isComponentActionsPresent()).to.be.false;
+ });
+
+ it("has delete and no add components", function() {
+ this.mockAdd.returns([]);
+ this.mockDelete.returns([{}]);
+ expect(mixin.isComponentActionsPresent()).to.be.true;
+ });
+
+ it("no delete and has add components", function() {
+ this.mockAdd.returns([{}]);
+ this.mockDelete.returns([]);
+ expect(mixin.isComponentActionsPresent()).to.be.true;
+ });
+ });
+
+ describe("#getComponentsToDelete()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.HostComponent, 'find').returns([
+ Em.Object.create({
+ componentName: 'C1',
+ hostName: 'host1'
+ })
+ ]);
+ });
+
+ afterEach(function() {
+ App.HostComponent.find.restore();
+ });
+
+ it("should return array of components to delete", function() {
+ var configActionComponents = [
+ {
+ configActionComponent: {
+ action: 'delete',
+ componentName: 'C1',
+ hostName: 'host1'
+ }
+ }
+ ];
+ expect(mixin.getComponentsToDelete(configActionComponents)).to.be.eql([{
+ action: 'delete',
+ componentName: 'C1',
+ hostName: 'host1'
+ }]);
+ });
+ });
+
+ describe("#getComponentsToAdd()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.StackServiceComponent, 'find').returns([
+ Em.Object.create({
+ componentName: 'C1',
+ serviceName: 'S1'
+ })
+ ]);
+ sinon.stub(App.Service, 'find').returns([
+ Em.Object.create({
+ serviceName: 'S1',
+ hostComponents: [
+ Em.Object.create({
+ componentName: 'C1',
+ hostName: 'host2'
+ })
+ ]
+ })
+ ]);
+ });
+
+ afterEach(function() {
+ App.StackServiceComponent.find.restore();
+ App.Service.find.restore();
+ });
+
+ it("should return array of components to add", function() {
+ var configActionComponents = [
+ {
+ configActionComponent: {
+ action: 'add',
+ componentName: 'C1',
+ hostName: 'host1'
+ }
+ }
+ ];
+ expect(mixin.getComponentsToAdd(configActionComponents)).to.be.eql([{
+ action: 'add',
+ componentName: 'C1',
+ hostName: 'host1'
+ }]);
+ });
+ });
+
+ describe("#doComponentDeleteActions()", function () {
+
+ beforeEach(function() {
+ this.mockDelete = sinon.stub(mixin, 'getComponentsToDelete');
+ sinon.stub(App.StackServiceComponent, 'find').returns([
+ Em.Object.create({
+ componentName: 'C1',
+ displayName: 'c1'
+ })
+ ]);
+ sinon.stub(mixin, 'setRefreshYarnQueueRequest');
+ sinon.stub(mixin, 'getInstallHostComponentsRequest').returns({});
+ sinon.stub(mixin, 'getDeleteHostComponentRequest').returns({});
+ sinon.stub(mixin, 'setOrderIdForBatches');
+ });
+
+ afterEach(function() {
+ this.mockDelete.restore();
+ App.StackServiceComponent.find.restore();
+ mixin.setRefreshYarnQueueRequest.restore();
+ mixin.getDeleteHostComponentRequest.restore();
+ mixin.setOrderIdForBatches.restore();
+ mixin.getInstallHostComponentsRequest.restore();
+ });
+
+ it("App.ajax.send should not be called", function() {
+ this.mockDelete.returns([]);
+ mixin.doComponentDeleteActions();
+ expect(testHelpers.findAjaxRequest('name', 'common.batch.request_schedules')).to.not.exists;
+ });
+
+ it("App.ajax.send should be called", function() {
+ this.mockDelete.returns([{
+ componentName: 'C1',
+ hostName: 'host1'
+ }]);
+ mixin.doComponentDeleteActions();
+ var args = testHelpers.findAjaxRequest('name', 'common.batch.request_schedules');
+ expect(args[0]).to.be.eql({
+ name: 'common.batch.request_schedules',
+ sender: mixin,
+ data: {
+ intervalTimeSeconds: 1,
+ tolerateSize: 0,
+ batches: [{}, {}]
+ }
+ });
+ });
+ });
+
+ describe("#doComponentAddActions()", function () {
+
+ beforeEach(function() {
+ this.mockAdd = sinon.stub(mixin, 'getComponentsToAdd');
+ sinon.stub(mixin, 'getDependentComponents').returns([]);
+ sinon.stub(App.StackServiceComponent, 'find').returns([
+ Em.Object.create({
+ componentName: 'C1',
+ displayName: 'c1'
+ })
+ ]);
+ sinon.stub(mixin, 'setCreateComponentRequest');
+ sinon.stub(mixin, 'getCreateHostComponentsRequest').returns({});
+ sinon.stub(mixin, 'getInstallHostComponentsRequest').returns({});
+ sinon.stub(mixin, 'setRefreshYarnQueueRequest');
+ sinon.stub(mixin, 'getStartHostComponentsRequest').returns({});
+ sinon.stub(mixin, 'setOrderIdForBatches');
+ sinon.stub(stringUtils, 'getFormattedStringFromArray').returns('c1');
+ });
+
+ afterEach(function() {
+ this.mockAdd.restore();
+ mixin.getDependentComponents.restore();
+ App.StackServiceComponent.find.restore();
+ mixin.setCreateComponentRequest.restore();
+ mixin.getCreateHostComponentsRequest.restore();
+ mixin.getInstallHostComponentsRequest.restore();
+ mixin.setRefreshYarnQueueRequest.restore();
+ mixin.getStartHostComponentsRequest.restore();
+ mixin.setOrderIdForBatches.restore();
+ stringUtils.getFormattedStringFromArray.restore();
+ });
+
+ it("App.ajax.send should not be called", function() {
+ this.mockAdd.returns([]);
+ mixin.doComponentAddActions();
+ expect(testHelpers.findAjaxRequest('name', 'common.batch.request_schedules')).to.not.exists;
+ });
+
+ it("App.ajax.send should be called", function() {
+ this.mockAdd.returns([{
+ componentName: 'C1',
+ hostName: 'host1',
+ isClient: false
+ }]);
+ mixin.doComponentAddActions();
+ var args = testHelpers.findAjaxRequest('name', 'common.batch.request_schedules');
+ expect(args[0]).to.be.eql({
+ name: 'common.batch.request_schedules',
+ sender: mixin,
+ data: {
+ intervalTimeSeconds: 1,
+ tolerateSize: 0,
+ batches: [{}, {}, {}]
+ }
+ });
+ });
+ });
+
+ describe("#getDependentComponents()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.StackServiceComponent, 'find').returns(Em.Object.create({
+ dependencies: [{
+ scope: 'host',
+ componentName: 'C2'
+ }],
+ isClient: false
+ }));
+ sinon.stub(App.HostComponent, 'find').returns([]);
+ });
+
+ afterEach(function() {
+ App.StackServiceComponent.find.restore();
+ App.HostComponent.find.restore();
+ });
+
+ it("should return dependent components", function() {
+ var componentsToAdd = [{
+ componentName: 'C1',
+ hostName: 'host1'
+ }];
+ expect(mixin.getDependentComponents(componentsToAdd)).to.be.eql([
+ {
+ componentName: 'C2',
+ hostName: 'host1',
+ isClient: false
+ }
+ ]);
+ });
+ });
+
+ describe("#setOrderIdForBatches()", function () {
+
+ it("should set order_id", function() {
+ var batches = [{}, {}, {}];
+ mixin.setOrderIdForBatches(batches);
+ expect(batches).to.be.eql([
+ {order_id: 1},
+ {order_id: 2},
+ {order_id: 3}
+ ]);
+ });
+ });
+
+ describe("#getCreateHostComponentsRequest()", function () {
+
+ it("App.ajax.send should be called", function() {
+ expect(mixin.getCreateHostComponentsRequest('host1', ['C1'])).to.be.eql({
+ "type": 'POST',
+ "uri": "/api/v1/clusters/mycluster/hosts",
+ "RequestBodyInfo": {
+ "RequestInfo": {
+ "query": "Hosts/host_name.in(host1)"
+ },
+ "Body": {
+ "host_components": [{
+ "HostRoles": {
+ "component_name": 'C1'
+ }
+ }]
+ }
+ }
+ });
+ });
+ });
+
+ describe("#getInstallHostComponentsRequest()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'getUpdateHostComponentsRequest').returns({});
+ });
+
+ afterEach(function() {
+ mixin.getUpdateHostComponentsRequest.restore();
+ });
+
+ it("should return request object", function() {
+ expect(mixin.getInstallHostComponentsRequest('host1', [{componentName: 'C1'}])).to.be.eql({});
+ expect(mixin.getUpdateHostComponentsRequest.calledWith(
+ 'host1',
+ [{componentName: 'C1'}],
+ App.HostComponentStatus.stopped,
+ Em.I18n.t('requestInfo.installComponents'))).to.be.true;
+ });
+ });
+
+ describe("#getStartHostComponentsRequest()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'getUpdateHostComponentsRequest').returns({});
+ });
+
+ afterEach(function() {
+ mixin.getUpdateHostComponentsRequest.restore();
+ });
+
+ it("should return request object", function() {
+ expect(mixin.getStartHostComponentsRequest('host1', [{componentName: 'C1'}])).to.be.eql({});
+ expect(mixin.getUpdateHostComponentsRequest.calledWith(
+ 'host1',
+ [{componentName: 'C1'}],
+ App.HostComponentStatus.started,
+ Em.I18n.t('requestInfo.startHostComponents'))).to.be.true;
+ });
+ });
+
+ describe("#getUpdateHostComponentsRequest()", function () {
+
+ it("should return request object", function() {
+ expect(mixin.getUpdateHostComponentsRequest('host1', ['C1', 'C2'], 'INSTALLED', 'context')).to.be.eql({
+ "type": 'PUT',
+ "uri": "/api/v1/clusters/mycluster/hosts/host1/host_components",
+ "RequestBodyInfo": {
+ "RequestInfo": {
+ "context": 'context',
+ "operation_level": {
+ "level": "HOST",
+ "cluster_name": 'mycluster',
+ "host_names": 'host1'
+ },
+ "query": "HostRoles/component_name.in(C1,C2)"
+ },
+ "Body": {
+ "HostRoles": {
+ "state": 'INSTALLED'
+ }
+ }
+ }
+ });
+ });
+ });
+
+ describe("#getDeleteHostComponentRequest()", function () {
+
+ it("should return request object", function() {
+ expect(mixin.getDeleteHostComponentRequest('host1', 'C1')).to.be.eql({
+ "type": 'DELETE',
+ "uri": "/api/v1/clusters/mycluster/hosts/host1/host_components/C1"
+ });
+ });
+ });
+
+ describe("#setCreateComponentRequest()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.StackServiceComponent, 'find').returns([Em.Object.create({
+ componentName: 'C1',
+ serviceName: 'S1'
+ })]);
+ sinon.stub(App.Service, 'find').returns([Em.Object.create({
+ serviceName: 'S1',
+ serviceComponents: []
+ })]);
+ });
+
+ afterEach(function() {
+ App.StackServiceComponent.find.restore();
+ App.Service.find.restore();
+ });
+
+ it("should add batch", function() {
+ var batches = [];
+ mixin.setCreateComponentRequest(batches, ["C1"]);
+ expect(batches).to.be.eql([
+ {
+ "type": 'POST',
+ "uri": "/api/v1/clusters/mycluster/services/S1/components/C1"
+ }
+ ]);
+
+ });
+ });
+
+ describe("#setRefreshYarnQueueRequest()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.Service, 'find').returns(Em.Object.create({
+ hostComponents: [Em.Object.create({
+ componentName: 'RESOURCEMANAGER',
+ hostName: 'host1'
+ })]
+ }));
+ });
+
+ afterEach(function() {
+ App.Service.find.restore();
+ });
+
+ it("should not add a batch", function() {
+ var batches = [];
+ mixin.set('allConfigs', []);
+ mixin.setRefreshYarnQueueRequest(batches);
+ expect(batches).to.be.empty;
+ });
+
+ it("should add a batch", function() {
+ var batches = [];
+ mixin.set('allConfigs', [Em.Object.create({
+ filename: 'capacity-scheduler.xml',
+ value: 'val1',
+ initialValue: 'val2'
+ })]);
+ mixin.setRefreshYarnQueueRequest(batches);
+ expect(batches).to.be.eql([{
+ "type": 'POST',
+ "uri": "/api/v1/clusters/mycluster/requests",
+ "RequestBodyInfo": {
+ "RequestInfo": {
+ "context": Em.I18n.t('services.service.actions.run.yarnRefreshQueues.context'),
+ "command": "REFRESHQUEUES",
+ "parameters/forceRefreshConfigTags": "capacity-scheduler"
+ },
+ "Requests/resource_filters": [
+ {
+ service_name: "YARN",
+ component_name: "RESOURCEMANAGER",
+ hosts: "host1"
+ }
+ ]
+ }
+ }]);
+ });
+ });
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/test/mixins/main/service/configs/config_overridable_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/main/service/configs/config_overridable_test.js b/ambari-web/test/mixins/main/service/configs/config_overridable_test.js
index 3c88819..b1eb099 100644
--- a/ambari-web/test/mixins/main/service/configs/config_overridable_test.js
+++ b/ambari-web/test/mixins/main/service/configs/config_overridable_test.js
@@ -19,6 +19,7 @@
var App = require('app');
require('mixins/main/service/configs/config_overridable');
+var testHelpers = require('test/helpers');
var configOverridable;
@@ -28,13 +29,19 @@ var configGroups = [
Em.Object.create({name: 'configGroup3'})
];
-describe('App.Decommissionable', function () {
+describe('App.ConfigOverridable', function () {
beforeEach(function () {
- configOverridable = Em.Object.create(App.ConfigOverridable);
+ configOverridable = Em.Object.create(App.ConfigOverridable, {
+ controller: Em.Object.create({
+ loadConfigGroups: Em.K,
+ doSelectConfigGroup: Em.K
+ }),
+ isView: true
+ });
});
- describe('#validate of Config Group Selection Creation Dialog', function () {
+ describe('#launchConfigGroupSelectionCreationDialog()', function () {
var testCases = [
{
@@ -92,4 +99,348 @@ describe('App.Decommissionable', function () {
});
});
+ describe("#createOverrideProperty()", function () {
+
+ beforeEach(function() {
+ sinon.stub(configOverridable, 'launchConfigGroupSelectionCreationDialog');
+ sinon.stub(App.ModalPopup, 'show');
+ sinon.stub(App.config, 'createOverride');
+ });
+
+ afterEach(function() {
+ configOverridable.launchConfigGroupSelectionCreationDialog.restore();
+ App.ModalPopup.show.restore();
+ App.config.createOverride.restore();
+ });
+
+ it("App.ModalPopup.show should be called", function() {
+ var event = {
+ contexts: [
+ Em.Object.create({
+ isUserProperty: true,
+ isNotSaved: true
+ })
+ ]
+ };
+ configOverridable.set('controller.name', '');
+ configOverridable.createOverrideProperty(event);
+ expect(App.ModalPopup.show.calledOnce).to.be.true;
+ });
+
+ it("launchConfigGroupSelectionCreationDialogshould be called", function() {
+ var event = {
+ contexts: [
+ Em.Object.create()
+ ]
+ };
+ configOverridable.set('controller.selectedConfigGroup', Em.Object.create({
+ isDefault: true
+ }));
+ configOverridable.createOverrideProperty(event);
+ expect(configOverridable.launchConfigGroupSelectionCreationDialog.calledOnce).to.be.true;
+ });
+
+ it("App.config.createOverride be called", function() {
+ var event = {
+ contexts: [
+ Em.Object.create({
+ widget: true,
+ value: 'val'
+ })
+ ]
+ };
+ configOverridable.set('controller.selectedConfigGroup', Em.Object.create({
+ isDefault: false
+ }));
+ configOverridable.createOverrideProperty(event);
+ expect(App.config.createOverride.calledOnce).to.be.true;
+ });
+ });
+
+ describe("#postNewConfigurationGroup()", function () {
+
+ it("App.ajax.send should be called", function() {
+ var newConfigGroupData = {
+ properties: [],
+ name: 'cg1',
+ service_id: 'S1',
+ description: '',
+ desired_configs: [],
+ hosts: ['host1']
+ };
+ configOverridable.postNewConfigurationGroup(newConfigGroupData);
+
+ var args = testHelpers.findAjaxRequest('name', 'config_groups.create');
+ expect(args[0]).to.be.eql({
+ name: 'config_groups.create',
+ sender: configOverridable,
+ data: {
+ data: [{
+ "ConfigGroup": {
+ "group_name": 'cg1',
+ "tag": 'S1',
+ "description": '',
+ "desired_configs": [],
+ "hosts": [{host_name: 'host1'}]
+ }
+ }],
+ modelData: newConfigGroupData
+ },
+ success: 'postNewConfigurationGroupSuccess',
+ error: 'postNewConfigurationGroupError'
+ });
+ });
+ });
+
+ describe("#postNewConfigurationGroupSuccess()", function () {
+
+ beforeEach(function() {
+ sinon.stub(App.store, 'load');
+ sinon.stub(App.store, 'commit');
+ sinon.stub(App.ServiceConfigGroup, 'deleteTemporaryRecords');
+ configOverridable.postNewConfigurationGroupSuccess({
+ resources: [
+ {
+ ConfigGroup: {
+ id: 'cg1'
+ }
+ }
+ ]
+ }, {}, {modelData: {}});
+ });
+
+ afterEach(function() {
+ App.ServiceConfigGroup.deleteTemporaryRecords.restore();
+ App.store.commit.restore();
+ App.store.load.restore();
+ });
+
+ it("App.store.load should be called", function() {
+ expect(App.store.load.calledWith(App.ServiceConfigGroup, {id: 'cg1'})).to.be.true;
+ });
+
+ it("App.store.commit should be called", function() {
+ expect(App.store.commit.calledOnce).to.be.true;
+ });
+
+ it("App.ServiceConfigGroup.deleteTemporaryRecords should be called", function() {
+ expect(App.ServiceConfigGroup.deleteTemporaryRecords.calledOnce).to.be.true;
+ });
+ });
+
+ describe("#updateConfigurationGroup()", function () {
+
+ beforeEach(function() {
+ sinon.stub(configOverridable, 'getConfigGroupData');
+ });
+
+ afterEach(function() {
+ configOverridable.getConfigGroupData.restore();
+ });
+
+ it("App.ajax.send should be called", function() {
+ configOverridable.updateConfigurationGroup(Em.Object.create());
+ expect(testHelpers.findAjaxRequest('name', 'config_groups.update')).to.be.exist;
+ });
+ });
+
+ describe("#getConfigGroupData()", function () {
+
+ it("should return config group data", function() {
+ var configGroup = Em.Object.create({
+ name: 'cg1',
+ description: 'dsc',
+ service: {
+ id: 'S1'
+ },
+ hosts: ['host1'],
+ desiredConfigs: [{
+ site: 'type1',
+ tag: 'tag1'
+ }]
+ });
+ expect(configOverridable.getConfigGroupData(configGroup)).to.be.eql({
+ ConfigGroup: {
+ group_name: 'cg1',
+ description: 'dsc',
+ tag: 'S1',
+ hosts: [{
+ host_name: 'host1'
+ }],
+ desired_configs: [{
+ type: 'type1',
+ tag: 'tag1'
+ }]
+ }
+ });
+ });
+ });
+
+ describe("#launchSwitchConfigGroupOfHostDialog()", function () {
+ var mock = {
+ callback: Em.K
+ };
+
+ beforeEach(function() {
+ sinon.spy(App.ModalPopup, 'show');
+ sinon.stub(configOverridable, 'updateConfigurationGroup');
+ sinon.spy(mock, 'callback');
+ });
+
+ afterEach(function() {
+ configOverridable.updateConfigurationGroup.restore();
+ App.ModalPopup.show.restore();
+ mock.callback.restore();
+ });
+
+ it("updateConfigurationGroup should be called", function() {
+ var popup = configOverridable.launchSwitchConfigGroupOfHostDialog(Em.Object.create({
+ name: 'cg1',
+ isDefault: false,
+ hosts: ['host1']
+ }),
+ [],'host1', Em.K);
+ popup.onPrimary();
+ expect(configOverridable.updateConfigurationGroup.calledTwice).to.be.true;
+ });
+
+ it("callback should be called", function() {
+ var group = Em.Object.create({
+ name: 'cg1',
+ isDefault: false,
+ hosts: ['host1']
+ });
+ var popup = configOverridable.launchSwitchConfigGroupOfHostDialog(group, [], 'host1', mock.callback);
+ popup.onPrimary();
+ expect(mock.callback.calledOnce).to.be.true;
+ });
+ });
+
+ describe("#deleteConfigurationGroup()", function () {
+
+ it("App.ajax.send should be called", function() {
+ configOverridable.deleteConfigurationGroup(Em.Object.create());
+ expect(testHelpers.findAjaxRequest('name', 'common.delete.config_group')).to.be.exist;
+ });
+ });
+
+ describe("#deleteConfigurationGroupSuccess()", function () {
+ var group = Em.Object.create({
+ id: 'cg1',
+ stateManager: Em.Object.create({
+ transitionTo: Em.K
+ })
+ });
+
+ beforeEach(function() {
+ sinon.stub(App.ServiceConfigGroup, 'find').returns([
+ group
+ ]);
+ sinon.stub(App.configGroupsMapper, 'deleteRecord');
+ });
+
+ afterEach(function() {
+ App.ServiceConfigGroup.find.restore();
+ App.configGroupsMapper.deleteRecord.restore();
+ });
+
+ it("App.configGroupsMapper.deleteRecord should be called", function() {
+ configOverridable.deleteConfigurationGroupSuccess({}, {}, {id: 'cg1'});
+ expect(App.configGroupsMapper.deleteRecord.calledWith(group)).to.be.true;
+ });
+
+ it("App.configGroupsMapper.deleteRecord should not be called", function() {
+ configOverridable.deleteConfigurationGroupSuccess({}, {}, {id: 'cg2'});
+ expect(App.configGroupsMapper.deleteRecord.called).to.be.false;
+ });
+ });
+
+ describe("#saveGroupConfirmationPopup()", function () {
+ var group = Em.Object.create({
+ serviceName: 'S1',
+ name: 'cg1'
+ });
+ var mock = {
+ manageConfigurationGroups: Em.K
+ };
+
+ beforeEach(function() {
+ sinon.stub(configOverridable.get('controller'), 'loadConfigGroups').returns({
+ done: function (callback) {
+ callback();
+ }
+ });
+ sinon.stub(configOverridable.get('controller'), 'doSelectConfigGroup');
+ sinon.stub(App.ServiceConfigGroup, 'find').returns([group]);
+ sinon.spy(App.ModalPopup, 'show');
+ sinon.stub(App.router, 'get').returns(mock);
+ sinon.spy(mock, 'manageConfigurationGroups');
+ });
+
+ afterEach(function() {
+ configOverridable.get('controller').loadConfigGroups.restore();
+ configOverridable.get('controller').doSelectConfigGroup.restore();
+ App.ServiceConfigGroup.find.restore();
+ App.ModalPopup.show.restore();
+ App.router.get.restore();
+ mock.manageConfigurationGroups.restore();
+ });
+
+ it("onPrimary", function() {
+ configOverridable.set('controller.name', 'mainServiceInfoConfigsController');
+ configOverridable.set('controller.content', Em.Object.create({
+ serviceName: 'S1'
+ }));
+ var popup = configOverridable.saveGroupConfirmationPopup('cg1');
+ popup.onPrimary();
+ expect(configOverridable.get('controller').doSelectConfigGroup.calledWith({context: group})).to.be.true;
+ });
+
+ it("onSecondary", function() {
+ configOverridable.set('controller.content', Em.Object.create({
+ serviceName: 'S1'
+ }));
+ var popup = configOverridable.saveGroupConfirmationPopup('cg1');
+ popup.onSecondary();
+ expect(mock.manageConfigurationGroups.calledWith(null, Em.Object.create({
+ serviceName: 'S1'
+ }))).to.be.true;
+ });
+ });
+
+ describe("#persistConfigGroups()", function () {
+ var mockInstaller = Em.Object.create({
+ saveServiceConfigGroups: Em.K
+ });
+ var mockStep7 = Em.Object.create({
+ content: Em.Object.create({
+ controllerName: 'addServiceController'
+ })
+ });
+
+ beforeEach(function() {
+ sinon.stub(mockInstaller, 'saveServiceConfigGroups');
+ this.mock = sinon.stub(App.router, 'get');
+ sinon.stub(App.clusterStatus, 'setClusterStatus');
+ this.mock.withArgs('installerController').returns(mockInstaller);
+ this.mock.withArgs('wizardStep7Controller').returns(mockStep7);
+ configOverridable.persistConfigGroups();
+ });
+
+ afterEach(function() {
+ App.clusterStatus.setClusterStatus.restore();
+ App.router.get.restore();
+ this.mock.restore();
+ mockInstaller.saveServiceConfigGroups.restore();
+ });
+
+ it("saveServiceConfigGroups should be called", function() {
+ expect(mockInstaller.saveServiceConfigGroups.calledWith(mockStep7, true)).to.be.true;
+ });
+
+ it("App.clusterStatus.setClusterStatus should be called", function() {
+ expect(App.clusterStatus.setClusterStatus.calledOnce).to.be.true;
+ });
+ });
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/07b42367/ambari-web/test/mixins/main/service/configs/widget_popover_support_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/main/service/configs/widget_popover_support_test.js b/ambari-web/test/mixins/main/service/configs/widget_popover_support_test.js
index 449ff5d..d4057b8 100644
--- a/ambari-web/test/mixins/main/service/configs/widget_popover_support_test.js
+++ b/ambari-web/test/mixins/main/service/configs/widget_popover_support_test.js
@@ -16,4 +16,167 @@
* limitations under the License.
*/
-describe('App.WidgetPopoverSupport', function () {});
\ No newline at end of file
+require('mixins/main/service/configs/widget_popover_support');
+
+var mixin;
+
+describe('App.WidgetPopoverSupport', function () {
+
+ beforeEach(function() {
+ mixin = Em.Object.create(App.WidgetPopoverSupport, {
+ stepConfigs: [],
+ content: Em.Object.create(),
+ on: Em.K,
+ $: Em.K
+ });
+ });
+
+ describe("#popoverPlacement", function () {
+
+ var testCases = [
+ {
+ sectionLastColumn: false,
+ subSectionLastColumn: false,
+ expected: 'right'
+ },
+ {
+ sectionLastColumn: true,
+ subSectionLastColumn: false,
+ expected: 'right'
+ },
+ {
+ sectionLastColumn: false,
+ subSectionLastColumn: true,
+ expected: 'right'
+ },
+ {
+ sectionLastColumn: true,
+ subSectionLastColumn: true,
+ expected: 'left'
+ }
+ ];
+
+ testCases.forEach(function(test) {
+ it("subSection.isLastColumn = " + test.subSectionLastColumn +
+ "section.isLastColumn = " + test.sectionLastColumn, function() {
+ mixin.setProperties({
+ section: {
+ isLastColumn: test.sectionLastColumn
+ },
+ subSection: {
+ isLastColumn: test.subSectionLastColumn
+ }
+ });
+ mixin.propertyDidChange('popoverPlacement');
+ expect(mixin.get('popoverPlacement')).to.be.equal(test.expected);
+ });
+ });
+ });
+
+ describe("#initPopover()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'destroyPopover');
+ sinon.stub(App, 'popover');
+ sinon.stub(mixin, 'on');
+ sinon.stub(mixin, '$')
+ });
+
+ afterEach(function() {
+ mixin.on.restore();
+ App.popover.restore();
+ mixin.destroyPopover.restore();
+ mixin.$.restore();
+ });
+
+ it("destroyPopover should not be called", function() {
+ mixin.set('isPopoverEnabled', false);
+ mixin.initPopover();
+ expect(mixin.destroyPopover.called).to.be.false;
+ });
+
+ it("App.popover should not be called", function() {
+ mixin.set('isPopoverEnabled', false);
+ mixin.initPopover();
+ expect(App.popover.called).to.be.false;
+ });
+
+ it("on should not be called", function() {
+ mixin.set('isPopoverEnabled', false);
+ mixin.initPopover();
+ expect(mixin.on.called).to.be.false;
+ });
+
+ it("destroyPopover should be called", function() {
+ mixin.set('isPopoverEnabled', true);
+ mixin.initPopover();
+ expect(mixin.destroyPopover.calledOnce).to.be.true;
+ });
+
+ it("App.popover should be called", function() {
+ mixin.set('isPopoverEnabled', true);
+ mixin.initPopover();
+ expect(App.popover.calledOnce).to.be.true;
+ });
+
+ it("on should be called", function() {
+ mixin.set('isPopoverEnabled', true);
+ mixin.initPopover();
+ expect(mixin.on.calledWith('willDestroyElement', mixin, mixin.destroyPopover)).to.be.true;
+ });
+ });
+
+ describe("#destroyPopover()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'movePopover');
+ });
+
+ afterEach(function() {
+ mixin.movePopover.restore();
+ });
+
+ it("movePopover should be called", function() {
+ mixin.destroyPopover();
+ expect(mixin.movePopover.calledWith('destroy')).to.be.true;
+ });
+ });
+
+ describe("#hidePopover()", function () {
+
+ beforeEach(function() {
+ sinon.stub(mixin, 'movePopover');
+ });
+
+ afterEach(function() {
+ mixin.movePopover.restore();
+ });
+
+ it("movePopover should be called", function() {
+ mixin.hidePopover();
+ expect(mixin.movePopover.calledWith('hide')).to.be.true;
+ });
+ });
+
+ describe("#movePopover()", function () {
+ var mock = {
+ popover: Em.K
+ };
+
+ beforeEach(function() {
+ sinon.stub(mixin, '$').returns(mock);
+ sinon.stub(mock, 'popover');
+ });
+
+ afterEach(function() {
+ mock.popover.restore();
+ mixin.$.restore();
+ });
+
+ it("popover should be called", function() {
+ mixin.movePopover('action');
+ expect(mock.popover.calledWith('action')).to.be.true;
+ });
+ });
+
+});
\ No newline at end of file