ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From atk...@apache.org
Subject [3/3] ambari git commit: AMBARI-18097 Cover configurations mixins with unit tests. (atkach)
Date Wed, 10 Aug 2016 10:36:53 GMT
AMBARI-18097 Cover configurations mixins 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/32ef4d4d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/32ef4d4d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/32ef4d4d

Branch: refs/heads/trunk
Commit: 32ef4d4d05f0c3fe3ca060da39b93d3b0bd9b902
Parents: 5198b80
Author: Andrii Tkach <atkach@apache.org>
Authored: Wed Aug 10 13:28:25 2016 +0300
Committer: Andrii Tkach <atkach@apache.org>
Committed: Wed Aug 10 13:28:25 2016 +0300

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |    3 +
 ...onfig_with_override_recommendation_parser.js |   12 +-
 .../mixins/common/configs/configs_comparator.js |  119 +-
 .../app/mixins/common/configs/configs_loader.js |  104 +-
 .../app/mixins/common/configs/configs_saver.js  |  135 +-
 .../mixins/common/configs/enhanced_configs.js   |  245 ++--
 ..._with_override_recommendation_parser_test.js |  206 +++
 .../common/configs/configs_comparator_test.js   |  764 +++++++++++
 .../common/configs/configs_loader_test.js       |  497 +++++++
 .../mixins/common/configs/configs_saver_test.js |  966 +++++++++++++-
 .../common/configs/enhanced_configs_test.js     | 1231 +++++++++++++++++-
 11 files changed, 3996 insertions(+), 286 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/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 99b74e5..658b6c8 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -153,6 +153,9 @@ var files = [
   'test/mixins/common/configs/enhanced_configs_test',
   'test/mixins/common/configs/config_recommendations_test',
   'test/mixins/common/configs/config_recommendation_parser_test',
+  'test/mixins/common/configs/config_with_override_recommendation_parser_test',
+  'test/mixins/common/configs/configs_comparator_test',
+  'test/mixins/common/configs/configs_loader_test',
   'test/mixins/common/configs/configs_saver_test',
   'test/mixins/common/configs/toggle_isrequired_test',
   'test/mixins/common/widgets/export_metrics_mixin_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js b/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
index bb39451..f866451 100644
--- a/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
+++ b/ambari-web/app/mixins/common/configs/config_with_override_recommendation_parser.js
@@ -93,8 +93,12 @@ App.ConfigWithOverrideRecommendationParser = Em.Mixin.create(App.ConfigRecommend
     };
     var override = App.config.createOverride(config, coreObject, configGroup);
 
-    this.applyRecommendation(Em.get(config, 'name'), Em.get(config, 'filename'), configGroup.get('name'),
-      recommendedValue, this._getInitialValue(override), parentProperties);
+    this.applyRecommendation(Em.get(config, 'name'),
+                             Em.get(config, 'filename'),
+                             configGroup.get('name'),
+                             recommendedValue,
+                             this._getInitialValue(override),
+                             parentProperties);
   },
 
   /**
@@ -103,12 +107,10 @@ App.ConfigWithOverrideRecommendationParser = Em.Mixin.create(App.ConfigRecommend
    * @param {Object} stackProperty
    * @param {string} attr
    * @param {Number|String|Boolean} value
-   * @param {String} name
-   * @param {String} fileName
    * @param {App.ServiceConfigGroup} configGroup
    * @protected
    */
-  _updateOverrideBoundaries: function(stackProperty, attr, value, name, fileName, configGroup) {
+  _updateOverrideBoundaries: function(stackProperty, attr, value, configGroup) {
     if (!stackProperty.valueAttributes[configGroup.get('name')]) {
       stackProperty.valueAttributes[configGroup.get('name')] = {};
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/app/mixins/common/configs/configs_comparator.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_comparator.js b/ambari-web/app/mixins/common/configs/configs_comparator.js
index c7d8322..79820c0 100644
--- a/ambari-web/app/mixins/common/configs/configs_comparator.js
+++ b/ambari-web/app/mixins/common/configs/configs_comparator.js
@@ -77,7 +77,7 @@ App.ConfigsComparator = Em.Mixin.create({
     var serviceVersionMap = {};
     var configNamesMap = allConfigs.toWickMapByProperty('name');
     var serviceName = this.get('content.serviceName');
-    var compareVersionNumber = this.get('compareServiceVersion').get('version');
+    var compareVersionNumber = this.get('compareServiceVersion.version');
     //indicate whether compared versions are from non-default group
     var compareNonDefaultVersions = (json.items.length > 1);
 
@@ -88,32 +88,8 @@ App.ConfigsComparator = Em.Mixin.create({
 
     json.items.forEach(function (item) {
       item.configurations.forEach(function (configuration) {
-        if (serviceName == 'YARN' && configuration.type == 'capacity-scheduler') {
-          var configsToSkip = App.config.getPropertiesFromTheme('YARN');
-          // put all properties in a single textarea for capacity-scheduler
-          var value = '';
-          for (var prop in configuration.properties) {
-            if (configsToSkip.contains(App.config.configId(prop, configuration.type))) {
-              serviceVersionMap[item.service_config_version][prop + '-' + configuration.type] = {
-                name: prop,
-                value: configuration.properties[prop],
-                type: configuration.type,
-                tag: configuration.tag,
-                version: configuration.version,
-                service_config_version: item.service_config_version
-              };
-            } else {
-              value += prop + '=' + configuration.properties[prop] + '\n';
-            }
-          }
-          serviceVersionMap[item.service_config_version][configuration.type + '-' + configuration.type] = {
-            name: configuration.type,
-            value: value,
-            type: configuration.type,
-            tag: configuration.tag,
-            version: configuration.version,
-            service_config_version: item.service_config_version
-          };
+        if (serviceName === 'YARN' && configuration.type === 'capacity-scheduler') {
+          this.addCompareCSConfigs(configuration, serviceVersionMap, item);
         } else {
           for (var prop in configuration.properties) {
             serviceVersionMap[item.service_config_version][prop + '-' + configuration.type] = {
@@ -137,6 +113,18 @@ App.ConfigsComparator = Em.Mixin.create({
       }, this);
     }, this);
 
+    this.addCompareConfigs(compareNonDefaultVersions, allConfigs, serviceVersionMap);
+  },
+
+  /**
+   *
+   * @param {boolean} compareNonDefaultVersions
+   * @param {Array} allConfigs
+   * @param {object} serviceVersionMap
+   */
+  addCompareConfigs: function(compareNonDefaultVersions, allConfigs, serviceVersionMap) {
+    var compareVersionNumber = this.get('compareServiceVersion.version');
+
     if (compareNonDefaultVersions) {
       allConfigs.forEach(function (serviceConfig) {
         if (Em.get(serviceConfig, 'isRequiredByAgent') !== false) {
@@ -146,7 +134,7 @@ App.ConfigsComparator = Em.Mixin.create({
     } else {
       allConfigs.forEach(function (serviceConfig) {
         if (Em.get(serviceConfig, 'isRequiredByAgent') !== false) {
-          var serviceCfgVersionMap = serviceVersionMap[this.get('compareServiceVersion').get('version')];
+          var serviceCfgVersionMap = serviceVersionMap[this.get('compareServiceVersion.version')];
           var compareConfig = serviceCfgVersionMap[serviceConfig.name + '-' + App.config.getConfigTagFromFileName(serviceConfig.filename)];
           this.setCompareDefaultGroupConfig(serviceConfig, compareConfig);
         }
@@ -155,6 +143,40 @@ App.ConfigsComparator = Em.Mixin.create({
   },
 
   /**
+   * init compare configs for Capacity-scheduler
+   * @param {object} configuration
+   * @param {object} serviceVersionMap
+   * @param {object} item
+   */
+  addCompareCSConfigs: function(configuration, serviceVersionMap, item) {
+    var configsToSkip = App.config.getPropertiesFromTheme('YARN');
+    // put all properties in a single textarea for capacity-scheduler
+    var value = '';
+    for (var prop in configuration.properties) {
+      if (configsToSkip.contains(App.config.configId(prop, configuration.type))) {
+        serviceVersionMap[item.service_config_version][prop + '-' + configuration.type] = {
+          name: prop,
+          value: configuration.properties[prop],
+          type: configuration.type,
+          tag: configuration.tag,
+          version: configuration.version,
+          service_config_version: item.service_config_version
+        };
+      } else {
+        value += prop + '=' + configuration.properties[prop] + '\n';
+      }
+    }
+    serviceVersionMap[item.service_config_version][configuration.type + '-' + configuration.type] = {
+      name: configuration.type,
+      value: value,
+      type: configuration.type,
+      tag: configuration.tag,
+      version: configuration.version,
+      service_config_version: item.service_config_version
+    };
+  },
+
+  /**
    * set compare properties to service config of non-default group
    * @param serviceConfig
    * @param serviceVersionMap
@@ -164,25 +186,28 @@ App.ConfigsComparator = Em.Mixin.create({
    * @method setCompareConfigs
    */
   setCompareConfigs: function (serviceConfig, serviceVersionMap, compareVersion, selectedVersion) {
-    var compareConfig = serviceVersionMap[compareVersion][Em.get(serviceConfig, 'name') + '-' + App.config.getConfigTagFromFileName(Em.get(serviceConfig, 'filename'))];
-    var selectedConfig = serviceVersionMap[selectedVersion][Em.get(serviceConfig, 'name') + '-' + App.config.getConfigTagFromFileName(Em.get(serviceConfig, 'filename'))];
+    var tag = App.config.getConfigTagFromFileName(Em.get(serviceConfig, 'filename'));
+    var compareConfig = serviceVersionMap[compareVersion][Em.get(serviceConfig, 'name') + '-' + tag];
+    var selectedConfig = serviceVersionMap[selectedVersion][Em.get(serviceConfig, 'name') + '-' + tag];
+    var compareConfigs = [];
 
-    Em.set(serviceConfig, 'compareConfigs', []);
     Em.set(serviceConfig, 'isComparison', true);
 
     if (compareConfig && selectedConfig) {
-      Em.get(serviceConfig, 'compareConfigs').push(this.getComparisonConfig(serviceConfig, compareConfig));
-      Em.get(serviceConfig, 'compareConfigs').push(this.getComparisonConfig(serviceConfig, selectedConfig));
-      Em.set(serviceConfig, 'hasCompareDiffs', this.hasCompareDiffs(Em.get(serviceConfig,'compareConfigs')[0], Em.get(serviceConfig,'compareConfigs')[1]));
+      compareConfigs.push(this.getComparisonConfig(serviceConfig, compareConfig));
+      compareConfigs.push(this.getComparisonConfig(serviceConfig, selectedConfig));
+      Em.set(serviceConfig, 'hasCompareDiffs', this.hasCompareDiffs(compareConfigs[0], compareConfigs[1]));
     } else if (compareConfig && !selectedConfig) {
-      Em.get(serviceConfig, 'compareConfigs').push(this.getComparisonConfig(serviceConfig, compareConfig));
-      Em.get(serviceConfig, 'compareConfigs').push(this.getMockComparisonConfig(selectedConfig, selectedVersion));
+      compareConfigs.push(this.getComparisonConfig(serviceConfig, compareConfig));
+      compareConfigs.push(this.getMockComparisonConfig(selectedConfig, selectedVersion));
       Em.set(serviceConfig, 'hasCompareDiffs', true);
     } else if (!compareConfig && selectedConfig) {
-      Em.get(serviceConfig, 'compareConfigs').push(this.getMockComparisonConfig(selectedConfig, compareVersion));
-      Em.get(serviceConfig, 'compareConfigs').push(this.getComparisonConfig(serviceConfig, selectedConfig));
+      compareConfigs.push(this.getMockComparisonConfig(selectedConfig, compareVersion));
+      compareConfigs.push(this.getComparisonConfig(serviceConfig, selectedConfig));
       Em.set(serviceConfig, 'hasCompareDiffs', true);
     }
+
+    Em.set(serviceConfig, 'compareConfigs', compareConfigs);
   },
 
   /**
@@ -195,11 +220,12 @@ App.ConfigsComparator = Em.Mixin.create({
    */
   getMockComparisonConfig: function (serviceConfig, compareServiceVersion) {
     var compareObject = $.extend(true, {isComparison: false},  serviceConfig);
-    Em.set(compareObject, 'isEditable', false);
-
-    Em.set(compareObject, 'serviceVersion', App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + compareServiceVersion));
-    Em.set(compareObject, 'isMock', true);
-    Em.set(compareObject, 'displayType', 'label');
+    compareObject.setProperties({
+      isEditable: false,
+      serviceVersion: App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + compareServiceVersion),
+      isMock: true,
+      displayType: 'label'
+    });
     compareObject = App.ServiceConfigProperty.create(compareObject);
     compareObject.set('value', Em.I18n.t('common.property.undefined'));
     return compareObject;
@@ -225,7 +251,7 @@ App.ConfigsComparator = Em.Mixin.create({
       Em.set(compareObject, 'serviceVersion', App.ServiceConfigVersion.find(this.get('content.serviceName') + "_" + compareConfig.service_config_version));
       compareObject = App.ServiceConfigProperty.create(compareObject);
       compareObject.setProperties({
-        isFinal: !!compareConfig.isFinal,
+        isFinal: Boolean(compareConfig.isFinal),
         value: App.config.formatPropertyValue(serviceConfig, compareConfig.value),
         compareConfigs: null,
         isOriginalSCP: false
@@ -254,7 +280,7 @@ App.ConfigsComparator = Em.Mixin.create({
       Em.set(serviceConfig, 'hasCompareDiffs', Em.get(serviceConfig, 'isMock') || this.hasCompareDiffs(serviceConfig, compareObject));
       Em.get(serviceConfig, 'compareConfigs').push(compareObject);
       // user custom property or property that was added during upgrade
-    } else if (Em.get(serviceConfig, 'isUserProperty') || (!isEmptyProp && !compareConfig && Em.get(serviceConfig, 'isRequiredByAgent') !== false)) {
+    } else if (Em.get(serviceConfig, 'isUserProperty') || (!isEmptyProp && Em.get(serviceConfig, 'isRequiredByAgent') !== false)) {
       Em.get(serviceConfig, 'compareConfigs').push(this.getMockComparisonConfig(serviceConfig, this.get('compareServiceVersion.version')));
       Em.set(serviceConfig, 'hasCompareDiffs', true);
     }
@@ -295,7 +321,8 @@ App.ConfigsComparator = Em.Mixin.create({
       compareValue.sort();
     }
 
-    return (!objectUtils.deepEqual(originalValue, compareValue)) || (!!Em.get(originalConfig, 'isFinal') !== !!Em.get(compareConfig, 'isFinal'));
+    return (!objectUtils.deepEqual(originalValue, compareValue)) ||
+            (!!Em.get(originalConfig, 'isFinal') !== !!Em.get(compareConfig, 'isFinal'));
   },
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/app/mixins/common/configs/configs_loader.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_loader.js b/ambari-web/app/mixins/common/configs/configs_loader.js
index 115a3e0..eb56a89 100644
--- a/ambari-web/app/mixins/common/configs/configs_loader.js
+++ b/ambari-web/app/mixins/common/configs/configs_loader.js
@@ -69,29 +69,37 @@ App.ConfigsLoader = Em.Mixin.create(App.GroupsMappingMixin, {
     }
     this.set('allVersionsLoaded', true);
     if (this.get('preSelectedConfigVersion')) {
-      var preSelectedId = App.serviceConfigVersionsMapper.makeId(this.get('preSelectedConfigVersion.serviceName'), this.get('preSelectedConfigVersion.version'));
-      var defaultConfigVersion = App.ServiceConfigVersion.find(App.serviceConfigVersionsMapper.makeId(this.get('content.serviceName'), this.get('currentDefaultVersion')));
-      var preSelectedVersion = App.ServiceConfigVersion.find().someProperty('id', preSelectedId) ? this.get('preSelectedConfigVersion') : defaultConfigVersion;
-
-      this.set('selectedVersion', this.get('preSelectedConfigVersion.version'));
-      /** handling redirecting from config history page **/
-      var self = this;
-      this.loadConfigGroups(this.get('servicesToLoad')).done(function() {
-        var selectedGroup = App.ServiceConfigGroup.find().find(function(g) {
-          return g.get('serviceName') === preSelectedVersion.get('serviceName')
-            && (g.get('name') === preSelectedVersion.get('groupName') || preSelectedVersion.get('groupName') === App.ServiceConfigGroup.defaultGroupName && g.get('isDefault'));
-        });
-        self.set('selectedConfigGroup', selectedGroup);
-        self.loadSelectedVersion(preSelectedVersion.get('version'), selectedGroup);
-        self.set('preSelectedConfigVersion', null);
-        preSelectedVersion = null;
-      });
+      this.loadPreSelectedConfigVersion();
     } else {
       this.set('selectedVersion', this.get('currentDefaultVersion'));
     }
   },
 
   /**
+   * @method loadPreSelectedConfigVersion
+   */
+  loadPreSelectedConfigVersion: function() {
+    var preSelectedId = App.serviceConfigVersionsMapper.makeId(this.get('preSelectedConfigVersion.serviceName'), this.get('preSelectedConfigVersion.version'));
+    var defaultConfigVersion = App.ServiceConfigVersion.find(App.serviceConfigVersionsMapper.makeId(this.get('content.serviceName'), this.get('currentDefaultVersion')));
+    var preSelectedVersion = App.ServiceConfigVersion.find().someProperty('id', preSelectedId) ? this.get('preSelectedConfigVersion') : defaultConfigVersion;
+
+    this.set('selectedVersion', this.get('preSelectedConfigVersion.version'));
+    /** handling redirecting from config history page **/
+    var self = this;
+    this.loadConfigGroups(this.get('servicesToLoad')).done(function() {
+      var selectedGroup = App.ServiceConfigGroup.find().find(function(g) {
+        return g.get('serviceName') === preSelectedVersion.get('serviceName')
+          && (g.get('name') === preSelectedVersion.get('groupName')
+              || preSelectedVersion.get('groupName') === App.ServiceConfigGroup.defaultGroupName && g.get('isDefault'));
+      });
+      self.set('selectedConfigGroup', selectedGroup);
+      self.loadSelectedVersion(preSelectedVersion.get('version'), selectedGroup);
+      self.set('preSelectedConfigVersion', null);
+      preSelectedVersion = null;
+    });
+  },
+
+  /**
    * loads current versions of current and dependent services
    * and all current version for config groups
    * @method loadCurrentVersions
@@ -119,14 +127,15 @@ App.ConfigsLoader = Em.Mixin.create(App.GroupsMappingMixin, {
    */
   loadCurrentVersionsSuccess: function (data, opt, params) {
     var self = this;
+    var serviceGroups = App.ServiceConfigGroup.find().filterProperty('serviceName', this.get('content.serviceName'));
     App.configGroupsMapper.map(data, true, params.serviceNames.split(','));
     this.loadConfigGroups(params.serviceNames.split(',')).done(function () {
       if (self.get('isHostsConfigsPage')) {
-        self.set('selectedConfigGroup', App.ServiceConfigGroup.find().filterProperty('serviceName', self.get('content.serviceName')).find(function (cg) {
+        self.set('selectedConfigGroup', serviceGroups.find(function (cg) {
               return !cg.get('isDefault') && cg.get('hosts').contains(self.get('host.hostName'));
-            }) || App.ServiceConfigGroup.find().filterProperty('serviceName', self.get('content.serviceName')).findProperty('isDefault'));
+            }) || serviceGroups.findProperty('isDefault'));
       } else {
-        self.set('selectedConfigGroup', App.ServiceConfigGroup.find().filterProperty('serviceName', self.get('content.serviceName')).findProperty('isDefault'));
+        self.set('selectedConfigGroup', serviceGroups.findProperty('isDefault'));
       }
       self.parseConfigData(data);
     });
@@ -146,24 +155,45 @@ App.ConfigsLoader = Em.Mixin.create(App.GroupsMappingMixin, {
       this.loadCurrentVersions();
     } else {
       //version of non-default group require properties from current version of default group to correctly display page
-      var versions = this.isVersionDefault(version) ? [version] : [this.get('currentDefaultVersion'), version];
-      switchToGroup = this.isVersionDefault(version) && !switchToGroup ? this.get('configGroups').findProperty('isDefault') : switchToGroup;
+      this.loadDefaultGroupVersion(version, switchToGroup);
+    }
+  },
 
-      if (this.get('dataIsLoaded') && switchToGroup) {
-        this.set('selectedConfigGroup', switchToGroup);
-      }
-      var selectedVersion = versions.length > 1 ? versions[1] : versions[0];
-      this.set('selectedVersion', selectedVersion);
-      this.trackRequest(App.ajax.send({
-        name: 'service.serviceConfigVersions.get.multiple',
-        sender: this,
-        data: {
-          serviceName: this.get('content.serviceName'),
-          serviceConfigVersions: versions,
-          additionalParams: this.get('dependentServiceNames.length') ? '|service_name.in(' + this.get('dependentServiceNames') + ')&is_current=true' : ''
-        },
-        success: 'loadSelectedVersionsSuccess'
-      }));
+  /**
+   *
+   * @param {string} version
+   * @param {?Em.Object} switchToGroup
+   */
+  loadDefaultGroupVersion: function(version, switchToGroup) {
+    var versions = this.isVersionDefault(version) ? [version] : [this.get('currentDefaultVersion'), version];
+    var selectedVersion = versions.length > 1 ? versions[1] : versions[0];
+
+    this.setSelectedConfigGroup(version, switchToGroup);
+    this.set('selectedVersion', selectedVersion);
+    this.trackRequest(App.ajax.send({
+      name: 'service.serviceConfigVersions.get.multiple',
+      sender: this,
+      data: {
+        serviceName: this.get('content.serviceName'),
+        serviceConfigVersions: versions,
+        additionalParams: this.get('dependentServiceNames.length') ? '|service_name.in(' + this.get('dependentServiceNames') + ')&is_current=true' : ''
+      },
+      success: 'loadSelectedVersionsSuccess'
+    }));
+  },
+
+  /**
+   *
+   * @param {string} version
+   * @param {?Em.Object} switchToGroup
+   */
+  setSelectedConfigGroup: function(version, switchToGroup) {
+    switchToGroup = (this.isVersionDefault(version) && !switchToGroup)
+      ? this.get('configGroups').findProperty('isDefault')
+      : switchToGroup;
+
+    if (this.get('dataIsLoaded') && switchToGroup) {
+      this.set('selectedConfigGroup', switchToGroup);
     }
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/app/mixins/common/configs/configs_saver.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_saver.js b/ambari-web/app/mixins/common/configs/configs_saver.js
index 832ec3a..6592203 100644
--- a/ambari-web/app/mixins/common/configs/configs_saver.js
+++ b/ambari-web/app/mixins/common/configs/configs_saver.js
@@ -120,41 +120,43 @@ App.ConfigsSaverMixin = Em.Mixin.create({
    * @method saveConfigs
    */
   saveConfigs: function () {
-    var selectedConfigGroup = this.get('selectedConfigGroup');
-    if (selectedConfigGroup.get('isDefault')) {
-
-      var data = [];
-      this.get('stepConfigs').forEach(function(stepConfig) {
-
-        var serviceConfig = this.getServiceConfigToSave(stepConfig.get('serviceName'), stepConfig.get('configs'));
+    if (this.get('selectedConfigGroup.isDefault')) {
+      this.saveConfigsForDefaultGroup();
+    } else {
+      this.saveConfigsForNonDefaultGroup();
+    }
+  },
 
-        if (serviceConfig)  {
-          data.push(serviceConfig);
+  saveConfigsForNonDefaultGroup: function() {
+    this.get('stepConfigs').forEach(function(stepConfig) {
+      var serviceName = stepConfig.get('serviceName');
+      var configs = stepConfig.get('configs');
+      var configGroup = this.getGroupFromModel(serviceName);
+      if (configGroup && !configGroup.get('isDefault')) {
+        var overriddenConfigs = this.getConfigsForGroup(configs, configGroup.get('name'));
+
+        if (Em.isArray(overriddenConfigs)) {
+          var successCallback = this.get('content.serviceName') === serviceName ? 'putConfigGroupChangesSuccess' : null;
+          this.saveGroup(overriddenConfigs, configGroup, this.get('serviceConfigVersionNote'), successCallback);
         }
-
-      }, this);
-
-      if (Em.isArray(data) && data.length) {
-        this.putChangedConfigurations(data, 'doPUTClusterConfigurationSiteSuccessCallback');
-      } else {
-        this.onDoPUTClusterConfigurations();
       }
-    } else {
+    }, this);
+  },
 
-      this.get('stepConfigs').forEach(function(stepConfig) {
-        var serviceName = stepConfig.get('serviceName');
-        var configs = stepConfig.get('configs');
-        var configGroup = this.getGroupFromModel(serviceName);
-        if (configGroup && !configGroup.get('isDefault')) {
+  saveConfigsForDefaultGroup: function() {
+    var data = [];
+    this.get('stepConfigs').forEach(function(stepConfig) {
+      var serviceConfig = this.getServiceConfigToSave(stepConfig.get('serviceName'), stepConfig.get('configs'));
 
-          var overriddenConfigs = this.getConfigsForGroup(configs, configGroup.get('name'));
+      if (serviceConfig)  {
+        data.push(serviceConfig);
+      }
+    }, this);
 
-          if (Em.isArray(overriddenConfigs)) {
-            var successCallback = this.get('content.serviceName') === serviceName ? 'putConfigGroupChangesSuccess' : null;
-            this.saveGroup(overriddenConfigs, configGroup, this.get('serviceConfigVersionNote'), successCallback);
-          }
-        }
-      }, this);
+    if (data.length) {
+      this.putChangedConfigurations(data, 'doPUTClusterConfigurationSiteSuccessCallback');
+    } else {
+      this.onDoPUTClusterConfigurations();
     }
   },
 
@@ -186,7 +188,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
    * @method hasUnsavedChanges
    */
   hasUnsavedChanges: function () {
-    return !Em.isNone(this.get('hash')) && this.get('hash') != this.getHash();
+    return !Em.isNone(this.get('hash')) && this.get('hash') !== this.getHash();
   },
 
   /*********************************** 1. PRE SAVE CHECKS ************************************/
@@ -289,10 +291,11 @@ App.ConfigsSaverMixin = Em.Mixin.create({
       overridenConfigs = overridenConfigs.concat(config.get('overrides'));
     });
     // find custom original properties that assigned to selected config group
-    return overridenConfigs.concat(stepConfigs.filterProperty('group')
-      .filter(function (config) {
+    return overridenConfigs.concat(
+      stepConfigs.filterProperty('group').filter(function (config) {
         return config.get('group.name') == configGroupName;
-      }));
+      })
+    );
   },
 
   /**
@@ -669,7 +672,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
    * @method onDoPUTClusterConfigurations
    */
   onDoPUTClusterConfigurations: function (doConfigActions) {
-    var header, message, messageClass, value, status = 'unknown', urlParams = '',
+    var status = 'unknown',
       result = {
         flag: this.get('saveConfigsFlag'),
         message: null,
@@ -683,36 +686,58 @@ App.ConfigsSaverMixin = Em.Mixin.create({
     }
 
     App.router.get('clusterController').updateClusterData();
-    App.router.get('updateController').updateComponentConfig(function () {
-    });
-    var flag = result.flag;
-    if (result.flag === true) {
-      header = Em.I18n.t('services.service.config.saved');
-      message = Em.I18n.t('services.service.config.saved.message');
-      messageClass = 'alert alert-success';
-      // warn the user if any of the components are in UNKNOWN state
-      urlParams += ',ServiceComponentInfo/installed_count,ServiceComponentInfo/total_count';
-      if (this.get('content.serviceName') === 'HDFS') {
-        urlParams += '&ServiceComponentInfo/service_name.in(HDFS)'
-      }
-    } else {
-      header = Em.I18n.t('common.failure');
-      message = result.message;
-      messageClass = 'alert alert-error';
-      value = result.value;
-    }
-    if (currentService){
-      App.get('router.clusterController').triggerQuickLinksUpdate();
+    App.router.get('updateController').updateComponentConfig(Em.K);
+    var popupOptions = this.getSaveConfigsPopupOptions(result);
+    if (currentService) {
+      App.router.get('clusterController').triggerQuickLinksUpdate();
     }
 
     //  update configs for service actions
     App.router.get('mainServiceItemController').loadConfigs();
 
-    this.showSaveConfigsPopup(header, flag, message, messageClass, value, status, urlParams, doConfigActions);
+    this.showSaveConfigsPopup(
+      popupOptions.header,
+      result.flag,
+      popupOptions.message,
+      popupOptions.messageClass,
+      popupOptions.value,
+      status,
+      popupOptions.urlParams,
+      doConfigActions);
     this.clearAllRecommendations();
   },
 
   /**
+   *
+   * @param {object} result
+   * @returns {object}
+   */
+  getSaveConfigsPopupOptions: function(result) {
+    var options;
+    if (result.flag === true) {
+      options = {
+        header: Em.I18n.t('services.service.config.saved'),
+        message: Em.I18n.t('services.service.config.saved.message'),
+        messageClass: 'alert alert-success',
+        urlParams: ',ServiceComponentInfo/installed_count,ServiceComponentInfo/total_count'
+      };
+
+      if (this.get('content.serviceName') === 'HDFS') {
+        options.urlParams += '&ServiceComponentInfo/service_name.in(HDFS)'
+      }
+    } else {
+      options = {
+        urlParams: '',
+        header: Em.I18n.t('common.failure'),
+        message: result.message,
+        messageClass: 'alert alert-error',
+        value: result.value
+      }
+    }
+    return options;
+  },
+
+  /**
    * Show save configs popup
    * @return {App.ModalPopup}
    * @private

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/app/mixins/common/configs/enhanced_configs.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/enhanced_configs.js b/ambari-web/app/mixins/common/configs/enhanced_configs.js
index 46bdb46..cc97180 100644
--- a/ambari-web/app/mixins/common/configs/enhanced_configs.js
+++ b/ambari-web/app/mixins/common/configs/enhanced_configs.js
@@ -38,7 +38,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
   /**
    * object with loaded recommendations
    *
-   * @type {Object}
+   * @type {?Object}
    */
   recommendationsConfigs: null,
 
@@ -98,26 +98,46 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    * @method setDependentGroups
    */
   setDependentGroups: function () {
-    if (this.get('selectedConfigGroup') && this.get('isControllerSupportsEnhancedConfigs') && !this.get('selectedConfigGroup.isDefault') && this.get('selectedService.dependentServiceNames.length')) {
+    if (this.shouldSetDependentConfigs()) {
       this.get('selectedService.dependentServiceNames').forEach(function (serviceName) {
         if (!this.get('selectedConfigGroup.dependentConfigGroups')[serviceName]) {
           var stepConfig = this.get('stepConfigs').findProperty('serviceName', serviceName);
           if (stepConfig) {
-            stepConfig.get('configGroups').filterProperty('isDefault', false).forEach(function (configGroup) {
-              this.get('selectedService.configGroups').filterProperty('isDefault', false).forEach(function (currentServiceGroup) {
-                if (currentServiceGroup.get('dependentConfigGroups')[serviceName] != configGroup.get('name')) {
-                  var dependentGroups = $.extend({},this.get('selectedConfigGroup.dependentConfigGroups'));
-                  dependentGroups[serviceName] = configGroup.get('name');
-                  this.set('selectedConfigGroup.dependentConfigGroups', dependentGroups);
-                }
-              }, this);
-            }, this);
+            this.setDependentConfigGroups(stepConfig, serviceName);
           }
         }
       }, this);
     }
   }.observes('selectedConfigGroup'),
 
+  /**
+   *
+   * @param {Em.Object} stepConfig
+   * @param {string} serviceName
+   */
+  setDependentConfigGroups: function(stepConfig, serviceName) {
+    stepConfig.get('configGroups').filterProperty('isDefault', false).forEach(function (configGroup) {
+      this.get('selectedService.configGroups').filterProperty('isDefault', false).forEach(function (currentServiceGroup) {
+        if (currentServiceGroup.get('dependentConfigGroups')[serviceName] !== configGroup.get('name')) {
+          var dependentGroups = $.extend({}, this.get('selectedConfigGroup.dependentConfigGroups'));
+          dependentGroups[serviceName] = configGroup.get('name');
+          this.set('selectedConfigGroup.dependentConfigGroups', dependentGroups);
+        }
+      }, this);
+    }, this);
+  },
+
+  /**
+   *
+   * @returns {boolean}
+   */
+  shouldSetDependentConfigs: function() {
+    return Boolean(this.get('selectedConfigGroup') &&
+           this.get('isControllerSupportsEnhancedConfigs') &&
+           !this.get('selectedConfigGroup.isDefault') &&
+           this.get('selectedService.dependentServiceNames.length'));
+  },
+
   /******************************METHODS THAT WORKS WITH DEPENDENT CONFIGS *************************************/
 
   /**
@@ -136,7 +156,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
       if (stepConfig) {
         var groups = stepConfig.get('configGroups');
         if (this.get('selectedConfigGroup.isDefault')) {
-          return groups.length ? groups.findProperty('isDefault', true) : null;
+          return groups.length ? groups.findProperty('isDefault') : null;
         } else {
           return groups.length ? groups.findProperty('name', this.get('selectedConfigGroup.dependentConfigGroups')[serviceName]) : null;
         }
@@ -157,43 +177,19 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    * @returns {$.ajax|null}
    */
   loadConfigRecommendations: function (changedConfigs, onComplete) {
-    var self = this;
     var updateDependencies = Em.isArray(changedConfigs) && changedConfigs.length > 0;
     var stepConfigs = this.get('stepConfigs');
+
     if (updateDependencies || Em.isNone(this.get('recommendationsConfigs'))) {
-      var configGroup = this.get('selectedConfigGroup');
       var recommendations = this.get('hostGroups');
-
-      var dataToSend = {
-        recommend: updateDependencies ? 'configuration-dependencies' : 'configurations',
-        hosts: this.get('hostNames'),
-        services: this.get('serviceNames')
-      };
-      if (updateDependencies) {
-        dataToSend.changed_configurations = changedConfigs;
-      }
-
-      if (configGroup && !configGroup.get('isDefault') && configGroup.get('hosts.length') > 0) {
-        recommendations.config_groups = [this.buildConfigGroupJSON(this.get('selectedService.configs'), configGroup)];
-      } else {
-        delete recommendations.config_groups;
-      }
+      var dataToSend = this.getConfigRecommendationsParams(updateDependencies);
+      this.modifyRecommendationConfigGroups(recommendations);
 
       if (stepConfigs.someProperty('serviceName', 'MISC')) {
-        recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(stepConfigs);
-        dataToSend.recommendations = recommendations;
+        this.addRecommendationRequestParams(recommendations, dataToSend, stepConfigs);
         return this.getRecommendationsRequest(dataToSend, onComplete);
       } else {
-        App.config.getClusterEnvConfigs().done(function (clusterEnvConfigs) {
-          stepConfigs = stepConfigs.concat(Em.Object.create({
-            serviceName: 'MISC',
-            configs: clusterEnvConfigs
-          }));
-
-          recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(stepConfigs);
-          dataToSend.recommendations = recommendations;
-          return self.getRecommendationsRequest(dataToSend, onComplete);
-        });
+        this.requestRecommendationsWithEnv(stepConfigs, recommendations, dataToSend, onComplete);
       }
     } else {
       if (onComplete) {
@@ -203,6 +199,66 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
     return $.Deferred().resolve().promise();
   },
 
+  /**
+   *
+   * @param recommendations
+   * @param dataToSend
+   * @param stepConfigs
+   */
+  addRecommendationRequestParams: function(recommendations, dataToSend, stepConfigs) {
+    recommendations.blueprint.configurations = blueprintUtils.buildConfigsJSON(stepConfigs);
+    dataToSend.recommendations = recommendations;
+  },
+
+  /**
+   *
+   * @param {Array} stepConfigs
+   * @param {object} recommendations
+   * @param {object} dataToSend
+   * @param {Function} onComplete
+   */
+  requestRecommendationsWithEnv: function(stepConfigs, recommendations, dataToSend, onComplete) {
+    var self = this;
+    App.config.getClusterEnvConfigs().done(function (clusterEnvConfigs) {
+      stepConfigs = stepConfigs.concat(Em.Object.create({
+        serviceName: 'MISC',
+        configs: clusterEnvConfigs
+      }));
+
+      self.addRecommendationRequestParams(recommendations, dataToSend, stepConfigs);
+      self.getRecommendationsRequest(dataToSend, onComplete);
+    });
+  },
+
+  /**
+   *
+   * @param {object} recommendations
+   */
+  modifyRecommendationConfigGroups: function(recommendations) {
+    var configGroup = this.get('selectedConfigGroup');
+
+    if (configGroup && !configGroup.get('isDefault') && configGroup.get('hosts.length') > 0) {
+      recommendations.config_groups = [this.buildConfigGroupJSON(this.get('selectedService.configs'), configGroup)];
+    } else {
+      delete recommendations.config_groups;
+    }
+  },
+
+  /**
+   *
+   * @param {boolean} updateDependencies
+   * @param {Array} changedConfigs
+   * @returns {{recommend: string, hosts: *, services: *, changed_configurations: *}}
+   */
+  getConfigRecommendationsParams: function(updateDependencies, changedConfigs) {
+    return {
+      recommend: updateDependencies ? 'configuration-dependencies' : 'configurations',
+      hosts: this.get('hostNames'),
+      services: this.get('serviceNames'),
+      changed_configurations: updateDependencies ? changedConfigs : undefined
+    };
+  },
+
   getRecommendationsRequest: function (dataToSend, callback) {
     var self = this;
     this.set('recommendationsInProgress', true);
@@ -232,14 +288,14 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    * @returns {boolean}
    */
   isConfigHasInitialState: function() {
-    return this.get('selectedConfigGroup.isDefault') && !Em.isNone(this.get('recommendationsConfigs'))
+    return Boolean(this.get('selectedConfigGroup.isDefault') && !Em.isNone(this.get('recommendationsConfigs'))
       && !this.get('stepConfigs').filter(function(stepConfig) {
       return stepConfig.get('changedConfigProperties').filter(function(c) {
         return !this.get('changedProperties').map(function(changed) {
           return App.config.configId(changed.propertyName, changed.propertyFileName);
         }).contains(App.config.configId(c.get('name'), c.get('filename')));
       }, this).length;
-    }, this).length;
+    }, this).length);
   },
 
   /**
@@ -324,15 +380,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
     Em.assert('invalid data - `data.resources[0].recommendations.blueprint.configurations` not defined ', data && data.resources[0] && Em.get(data.resources[0], 'recommendations.blueprint.configurations'));
     var recommendations = data.resources[0].recommendations;
     if (recommendations['config-groups'] && this.get('selectedConfigGroup') && !this.get('selectedConfigGroup.isDefault')) {
-      var configFroGroup = recommendations['config-groups'][0];
-      this.get('stepConfigs').forEach(function(stepConfig) {
-        var configGroup = this.getGroupForService(stepConfig.get('serviceName'));
-        if (configGroup) {
-          this.updateOverridesByRecommendations(configFroGroup.configurations, stepConfig.get('configs'), changedConfigs, configGroup);
-          this.updateOverridesByRecommendations(configFroGroup.dependent_configurations, stepConfig.get('configs'), changedConfigs, configGroup);
-          this.toggleProperty('forceUpdateBoundaries');
-        }
-      }, this);
+      this.saveConfigGroupsRecommendations(recommendations, changedConfigs);
     } else {
       var configObject = recommendations.blueprint.configurations;
       this.get('stepConfigs').forEach(function(stepConfig) {
@@ -344,6 +392,23 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
   },
 
   /**
+   *
+   * @param {object} recommendations
+   * @param {?Array} changedConfigs
+   */
+  saveConfigGroupsRecommendations: function(recommendations, changedConfigs) {
+    var configForGroup = recommendations['config-groups'][0];
+    this.get('stepConfigs').forEach(function(stepConfig) {
+      var configGroup = this.getGroupForService(stepConfig.get('serviceName'));
+      if (configGroup) {
+        this.updateOverridesByRecommendations(configForGroup.configurations, stepConfig.get('configs'), changedConfigs, configGroup);
+        this.updateOverridesByRecommendations(configForGroup.dependent_configurations, stepConfig.get('configs'), changedConfigs, configGroup);
+        this.toggleProperty('forceUpdateBoundaries');
+      }
+    }, this);
+  },
+
+  /**
    * method to show popup with dependent configs
    * @method showChangedDependentConfigs
    */
@@ -365,7 +430,7 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
    */
   onSaveRecommendedPopup: function(recommendations) {
     var propertiesToUpdate = recommendations.filter(function(c) {
-        return Em.get(c, 'saveRecommendedDefault') != Em.get(c, 'saveRecommended');
+        return Em.get(c, 'saveRecommendedDefault') !== Em.get(c, 'saveRecommended');
       }),
       propertiesToUndo = propertiesToUpdate.filterProperty('saveRecommended', false),
       propertiesToRedo = propertiesToUpdate.filterProperty('saveRecommended', true);
@@ -388,32 +453,66 @@ App.EnhancedConfigsMixin = Em.Mixin.create(App.ConfigWithOverrideRecommendationP
       var recommended = redo ? Em.get(p, 'recommendedValue') : Em.get(p, 'initialValue');
       var stepConfig = this.get('stepConfigs').findProperty('serviceName', Em.get(p, 'serviceName'));
       var config = stepConfig.get('configs').find(function(scp) {
-        return scp.get('name') == Em.get(p, 'propertyName') && scp.get('filename') == App.config.getOriginalFileName(Em.get(p, 'propertyFileName'));
+        return scp.get('name') === Em.get(p, 'propertyName') &&
+               scp.get('filename') === App.config.getOriginalFileName(Em.get(p, 'propertyFileName'));
       });
-      var selectedGroup = App.ServiceConfigGroup.find().filterProperty('serviceName', Em.get(p, 'serviceName')).findProperty('name', Em.get(p, 'configGroup'));
+      var selectedGroup = App.ServiceConfigGroup.find()
+        .filterProperty('serviceName', Em.get(p, 'serviceName'))
+        .findProperty('name', Em.get(p, 'configGroup'));
+
       if (selectedGroup.get('isDefault')) {
-        if (Em.isNone(recommended)) {
-          stepConfig.get('configs').removeObject(config);
-        } else if (Em.isNone(initial)) {
-          stepConfig.get('configs').pushObject(this._createNewProperty(Em.get(p, 'propertyName'), Em.get(p, 'propertyFileName'),Em.get(p, 'serviceName'),
-              recommended, App.configsCollection.getConfigByName(Em.get(p, 'propertyName'), Em.get(p, 'propertyFileName')).propertyDependsOn));
-        } else {
-          Em.set(config, 'value', recommended);
-        }
+        this.setRecommendedForDefaultGroup(recommended, stepConfig, p, initial, config);
       } else {
-        if (Em.isNone(recommended)) {
-          config.get('overrides').removeObject(config.getOverride(selectedGroup.get('name')));
-        } else if (Em.isNone(initial)) {
-          this._addConfigOverrideRecommendation(config, recommended, null, selectedGroup);
-        } else {
-          var override = config.getOverride(selectedGroup.get('name'));
-          if (override) {
-            override.set('value', recommended);
-          }
-        }
+        this.setRecommendedForGroup(recommended, selectedGroup, config, initial);
       }
     }, this);
   },
+
+  /**
+   *
+   * @param {string} recommended
+   * @param {Em.Object} selectedGroup
+   * @param {object} config
+   * @param {string}initial
+   */
+  setRecommendedForGroup: function(recommended, selectedGroup, config, initial) {
+    if (Em.isNone(recommended)) {
+      config.get('overrides').removeObject(config.getOverride(selectedGroup.get('name')));
+    } else if (Em.isNone(initial)) {
+      this._addConfigOverrideRecommendation(config, recommended, null, selectedGroup);
+    } else {
+      var override = config.getOverride(selectedGroup.get('name'));
+      if (override) {
+        override.set('value', recommended);
+      }
+    }
+  },
+
+  /**
+   *
+   * @param {string} recommended
+   * @param {Em.Object} stepConfig
+   * @param {object|Em.Object} prop
+   * @param {string} initial
+   * @param {object} config
+   */
+  setRecommendedForDefaultGroup: function(recommended, stepConfig, prop, initial, config) {
+    var name = Em.get(prop, 'propertyName'),
+        filename = Em.get(prop, 'propertyFileName');
+
+    if (Em.isNone(recommended)) {
+      stepConfig.get('configs').removeObject(config);
+    } else if (Em.isNone(initial)) {
+      stepConfig.get('configs').pushObject(this._createNewProperty(
+        name,
+        filename,
+        Em.get(prop, 'serviceName'),
+        recommended,
+        App.configsCollection.getConfigByName(name, filename).propertyDependsOn));
+    } else {
+      Em.set(config, 'value', recommended);
+    }
+  },
   
   saveInitialRecommendations: function() {
     this.get('recommendations').forEach(function (r) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/test/mixins/common/configs/config_with_override_recommendation_parser_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/configs/config_with_override_recommendation_parser_test.js b/ambari-web/test/mixins/common/configs/config_with_override_recommendation_parser_test.js
new file mode 100644
index 0000000..a14a14f
--- /dev/null
+++ b/ambari-web/test/mixins/common/configs/config_with_override_recommendation_parser_test.js
@@ -0,0 +1,206 @@
+/**
+ * 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');
+
+describe('App.ConfigWithOverrideRecommendationParser', function() {
+	var mixin;
+
+	beforeEach(function() {
+    mixin = Em.Object.create(App.ConfigWithOverrideRecommendationParser, {
+      parseRecommendations: Em.K,
+      _updateConfigByRecommendation: Em.K,
+      _removeConfigByRecommendation: Em.K,
+      getRecommendation: Em.K,
+      applyRecommendation: Em.K,
+      useInitialValue: Em.K,
+      _getInitialValue: Em.K
+    });
+	});
+
+  describe("#updateOverridesByRecommendations()", function () {
+
+    beforeEach(function() {
+      sinon.stub(mixin, 'parseRecommendations');
+    });
+
+    afterEach(function() {
+      mixin.parseRecommendations.restore();
+    });
+
+    it("parseRecommendations should be called", function() {
+      var configGroup = Em.Object.create({
+        name: 'g1',
+        isDefault: false
+      });
+      mixin.updateOverridesByRecommendations({}, [{}], [{}], configGroup);
+      expect(mixin.parseRecommendations.calledWith({}, [{}], [{}], configGroup)).to.be.true;
+    });
+  });
+
+  describe("#_updateOverride()", function () {
+    var config = Em.Object.create({
+      name: 'c1',
+      filename: 'f1',
+      getOverride: Em.K
+    });
+
+    beforeEach(function() {
+      this.mockUpdateValue = sinon.stub(mixin, 'allowUpdateProperty');
+      this.mockOverride = sinon.stub(config, 'getOverride');
+      sinon.stub(mixin, '_addConfigOverrideRecommendation');
+      sinon.stub(mixin, '_updateConfigByRecommendation');
+    });
+
+    afterEach(function() {
+      this.mockUpdateValue.restore();
+      this.mockOverride.restore();
+      mixin._addConfigOverrideRecommendation.restore();
+      mixin._updateConfigByRecommendation.restore();
+    });
+
+    it("_updateConfigByRecommendation should be called", function() {
+      this.mockOverride.returns({});
+      mixin._updateOverride(config, 'val', [], Em.Object.create());
+      expect(mixin._updateConfigByRecommendation.calledWith({}, 'val', [])).to.be.true;
+      expect(mixin._addConfigOverrideRecommendation.called).to.be.false;
+    });
+
+    it("_addConfigOverrideRecommendation should be called", function() {
+      this.mockUpdateValue.returns('val1');
+      mixin._updateOverride(config, 'val', [], Em.Object.create());
+      expect(mixin._addConfigOverrideRecommendation.calledWith(config, 'val', [], Em.Object.create())).to.be.true;
+      expect(mixin._updateConfigByRecommendation.called).to.be.false;
+    });
+
+    it("no methods should be called", function() {
+      this.mockUpdateValue.returns('');
+      this.mockOverride.returns(null);
+      mixin._updateOverride(config, 'val', [], Em.Object.create());
+      expect(mixin._addConfigOverrideRecommendation.called).to.be.false;
+      expect(mixin._updateConfigByRecommendation.called).to.be.false;
+    });
+  });
+
+  describe("#_removeOverride()", function () {
+    var property = Em.Object.create({
+      overrides: [],
+      getOverride: Em.K
+    });
+
+    beforeEach(function() {
+      sinon.stub(mixin, '_removeConfigByRecommendation');
+      this.mock = sinon.stub(property, 'getOverride');
+    });
+
+    afterEach(function() {
+      mixin._removeConfigByRecommendation.restore();
+      this.mock.restore();
+    });
+
+    it("no override", function() {
+      this.mock.returns(null);
+      mixin._removeOverride(property, [], [], Em.Object.create());
+      expect(mixin._removeConfigByRecommendation.calledWith(property, [], [])).to.be.true;
+    });
+
+    it("has override", function() {
+      this.mock.returns({});
+      mixin._removeOverride(property, [], [], Em.Object.create());
+      expect(mixin._removeConfigByRecommendation.calledWith({}, [], [])).to.be.true;
+    });
+  });
+
+  describe("#_addConfigOverrideRecommendation()", function () {
+    var config = Em.Object.create({
+      name: 'c1',
+      filename: 'f1',
+      serviceName: 'S1'
+    });
+
+    beforeEach(function() {
+      this.mockRecommendation = sinon.stub(mixin, 'getRecommendation');
+      sinon.stub(App.config, 'createOverride');
+      sinon.stub(mixin, 'useInitialValue').returns(false);
+      sinon.stub(mixin, 'applyRecommendation');
+      sinon.stub(mixin, '_getInitialValue').returns('init');
+    });
+
+    afterEach(function() {
+      this.mockRecommendation.restore();
+      App.config.createOverride.restore();
+      mixin.useInitialValue.restore();
+      mixin.applyRecommendation.restore();
+      mixin._getInitialValue.restore();
+    });
+
+    it("applyRecommendation should be called", function() {
+      mixin._addConfigOverrideRecommendation(config, 'val', [], Em.Object.create({name: 'g1'}));
+      expect(mixin.applyRecommendation.calledWith('c1', 'f1', 'g1', 'val', 'init', [])).to.be.true;
+    });
+
+    it("App.config.createOverride should be called, initialValue is null", function() {
+      this.mockRecommendation.returns(null);
+      mixin._addConfigOverrideRecommendation(config, 'val', [], Em.Object.create({name: 'g1'}));
+      expect(App.config.createOverride.calledWith(config, {
+        "value": 'val',
+        "recommendedValue": 'val',
+        "initialValue": null,
+        "savedValue": null,
+        "isEditable": true,
+        "errorMessage": '',
+        "warnMessage": ''
+      }, Em.Object.create({name: 'g1'}))).to.be.true;
+    });
+
+    it("App.config.createOverride should be called, initialValue is correct", function() {
+      this.mockRecommendation.returns({value: 'val1'});
+      mixin._addConfigOverrideRecommendation(config, 'val', [], Em.Object.create({name: 'g1'}));
+      expect(App.config.createOverride.calledWith(config, {
+        "value": 'val',
+        "recommendedValue": 'val',
+        "initialValue": 'val1',
+        "savedValue": 'val1',
+        "isEditable": true,
+        "errorMessage": '',
+        "warnMessage": ''
+      }, Em.Object.create({name: 'g1'}))).to.be.true;
+    });
+  });
+
+  describe("#_updateOverrideBoundaries()", function () {
+    var stackProperty = {
+      valueAttributes: {
+        g1: {
+          'attr1': 'true'
+        }
+      }
+    };
+
+    it("modify attributes on existing group", function() {
+      mixin._updateOverrideBoundaries(stackProperty, 'attr1', 'false', Em.Object.create({name: 'g1'}));
+      expect(stackProperty.valueAttributes['g1']['attr1']).to.be.equal('false');
+    });
+
+    it("modify attributes on new group", function() {
+      mixin._updateOverrideBoundaries(stackProperty, 'attr1', 'true', Em.Object.create({name: 'g2'}));
+      expect(stackProperty.valueAttributes['g2']['attr1']).to.be.equal('true');
+    });
+  });
+});
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/32ef4d4d/ambari-web/test/mixins/common/configs/configs_comparator_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/configs/configs_comparator_test.js b/ambari-web/test/mixins/common/configs/configs_comparator_test.js
new file mode 100644
index 0000000..dc7534c
--- /dev/null
+++ b/ambari-web/test/mixins/common/configs/configs_comparator_test.js
@@ -0,0 +1,764 @@
+/**
+ * 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 testHelpers = require('test/helpers');
+
+describe('App.ConfigsComparator', function() {
+	var mixin;
+
+	beforeEach(function() {
+    mixin = Em.Object.create(App.ConfigsComparator, {
+      compareServiceVersion: Em.Object.create({version: 'v1'}),
+      content: Em.Object.create()
+    });
+	});
+
+  describe("#loadCompareVersionConfigs()", function () {
+
+    beforeEach(function() {
+      this.mockIsDefault = sinon.stub(mixin, 'isVersionDefault');
+      sinon.stub(mixin, 'getCompareVersionConfigs').returns({
+        done: function(callback) {
+          callback({});
+          return this;
+        },
+        fail: Em.K
+      });
+      sinon.stub(mixin, 'initCompareConfig');
+    });
+
+    afterEach(function() {
+      this.mockIsDefault.restore();
+      mixin.getCompareVersionConfigs.restore();
+      mixin.initCompareConfig.restore();
+    });
+
+    describe("#compareServiceVersion is null", function () {
+      var config;
+
+      beforeEach(function() {
+        config = Em.Object.create();
+        mixin.set('compareServiceVersion', null);
+      });
+
+      it("result should be true", function() {
+        var dfd = mixin.loadCompareVersionConfigs([config]);
+        dfd.done(function(result) {
+          expect(result).to.be.false;
+        })
+      });
+
+      it("isCompareMode should be false", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.get('isCompareMode')).to.be.false;
+      });
+
+      it("config.isComparison should be false", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(config.get('isComparison')).to.be.false;
+      });
+    });
+
+    describe("#compareServiceVersion correct", function () {
+      var config;
+
+      beforeEach(function() {
+        mixin.set('compareServiceVersion', Em.Object.create({
+          version: 'v1'
+        }));
+        mixin.set('selectedVersion', 'v2');
+        config = Em.Object.create();
+      });
+
+      it("getCompareVersionConfigs should be called, default", function() {
+        this.mockIsDefault.returns(true);
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.getCompareVersionConfigs.calledWith(['v1'])).to.be.true;
+      });
+
+      it("getCompareVersionConfigs should be called, non-default", function() {
+        this.mockIsDefault.returns(false);
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.getCompareVersionConfigs.calledWith(['v1', 'v2'])).to.be.true;
+      });
+
+      it("config.isEditable should be false", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(config.get('isEditable')).to.be.false;
+      });
+
+      it("initCompareConfig should be called", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.initCompareConfig.calledWith([config], {})).to.be.true;
+      });
+
+      it("compareServiceVersion should be null", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.get('compareServiceVersion')).to.be.null;
+      });
+
+      it("isCompareMode should be true", function() {
+        mixin.loadCompareVersionConfigs([config]);
+        expect(mixin.get('isCompareMode')).to.be.true;
+      });
+
+      it("resolve should be true", function() {
+        var dfd = mixin.loadCompareVersionConfigs([config]);
+        dfd.done(function(result) {
+          expect(result).to.be.true;
+        });
+      });
+    });
+  });
+
+  describe("#initCompareConfig()", function () {
+
+    beforeEach(function() {
+      sinon.stub(mixin, 'addCompareConfigs');
+      sinon.stub(mixin, 'addCompareCSConfigs');
+      sinon.stub(mixin, 'getMockConfig').returns({name: 'mock'});
+      mixin.setProperties({
+        content: Em.Object.create({serviceName: 'S1'}),
+        compareServiceVersion: Em.Object.create({version: 'v1'})
+      });
+    });
+
+    afterEach(function() {
+      mixin.addCompareConfigs.restore();
+      mixin.addCompareCSConfigs.restore();
+      mixin.getMockConfig.restore();
+    });
+
+    it("empty json", function() {
+      var allConfigs = [
+        {
+          name: 'conf1'
+        }
+      ];
+      mixin.initCompareConfig(allConfigs, {items: []});
+      expect(mixin.addCompareConfigs.calledWith(false, allConfigs, {v1: {}})).to.be.true;
+    });
+
+    it("Capacity scheduler config", function() {
+      var allConfigs = [
+        {
+          name: 'conf1'
+        }
+      ];
+      var json = {
+        items: [
+          {
+            configurations: [{
+              type: 'capacity-scheduler'
+            }]
+          }
+        ]
+      };
+      mixin.set('content.serviceName', 'YARN');
+      mixin.set('selectedVersion', 'v2');
+      mixin.initCompareConfig(allConfigs, json);
+      expect(mixin.addCompareCSConfigs.calledWith({
+          type: 'capacity-scheduler'
+        }, {v1: {}}, {
+        configurations: [{
+          type: 'capacity-scheduler'
+        }]
+      })).to.be.true;
+      expect(mixin.addCompareConfigs.calledWith(false, allConfigs, {v1: {}})).to.be.true;
+    });
+
+    it("simple config", function() {
+      var allConfigs = [
+        {
+          name: 'prop1'
+        }
+      ];
+      var json = {
+        items: [
+          {
+            service_config_version: 'v1',
+            configurations: [{
+              type: 't1',
+              tag: 'tag1',
+              version: '1',
+              properties: {
+                prop1: 'val1'
+              }
+            }]
+          },
+          {
+            service_config_version: 'v2',
+            configurations: [{
+              tag: 'tag2',
+              type: 't2',
+              version: '2',
+              properties: {
+                prop2: 'val2'
+              },
+              properties_attributes: {
+                final: {
+                  prop2: 'true'
+                }
+              }
+            }]
+          }
+        ]
+      };
+      mixin.set('selectedVersion', 'v2');
+      mixin.initCompareConfig(allConfigs, json);
+      expect(mixin.addCompareConfigs.getCall(0).args[2]).to.be.eql({
+        v1: {
+          'prop1-t1': {
+            name: 'prop1',
+            value: 'val1',
+            type: 't1',
+            tag: 'tag1',
+            version: '1',
+            service_config_version: 'v1'
+          }
+        },
+        v2: {
+          'prop2-t2': {
+            name: 'prop2',
+            value: 'val2',
+            type: 't2',
+            tag: 'tag2',
+            version: '2',
+            service_config_version: 'v2',
+            isFinal: true
+          }
+        }
+      });
+      expect(mixin.addCompareConfigs.getCall(0).args[1]).to.be.eql(
+        [{name: 'prop1'}, {name: 'mock'}]
+      );
+      expect(mixin.addCompareConfigs.getCall(0).args[0]).to.be.true;
+    });
+  });
+
+  describe("#addCompareConfigs()", function () {
+
+    beforeEach(function() {
+      mixin.set('compareServiceVersion.version', 'v1');
+      mixin.set('selectedVersion', 'v2');
+      sinon.stub(mixin, 'setCompareConfigs');
+      sinon.stub(mixin, 'setCompareDefaultGroupConfig');
+      sinon.stub(App.config, 'getConfigTagFromFileName').returns('tag1');
+    });
+
+    afterEach(function() {
+      mixin.setCompareConfigs.restore();
+      mixin.setCompareDefaultGroupConfig.restore();
+      App.config.getConfigTagFromFileName.restore();
+    });
+
+    it("non-default version, isRequiredByAgent=false", function() {
+      mixin.addCompareConfigs(true, [{isRequiredByAgent: false}], {});
+      expect(mixin.setCompareConfigs.called).to.be.false;
+    });
+
+    it("non-default version, isRequiredByAgent=true", function() {
+      mixin.addCompareConfigs(true, [{isRequiredByAgent: true}], {});
+      expect(mixin.setCompareConfigs.calledWith(
+        {isRequiredByAgent: true},
+        {},
+        'v1',
+        'v2'
+      )).to.be.true;
+    });
+
+    it("default version, isRequiredByAgent=false", function() {
+      mixin.addCompareConfigs(false, [{isRequiredByAgent: false}], {});
+      expect(mixin.setCompareDefaultGroupConfig.called).to.be.false;
+    });
+
+    it("default version, isRequiredByAgent=true", function() {
+      var serviceVersionMap = {
+        'v1': {
+          'c1-tag1': {
+            name: 'c1'
+          }
+        }
+      };
+      mixin.addCompareConfigs(false, [{isRequiredByAgent: true, name: 'c1'}], serviceVersionMap);
+      expect(mixin.setCompareDefaultGroupConfig.calledWith(
+        {isRequiredByAgent: true, name: 'c1'},
+        {name: 'c1'}
+      )).to.be.true;
+    });
+  });
+
+  describe("#method", function () {
+
+    beforeEach(function() {
+      sinon.stub(App.config, 'getPropertiesFromTheme').returns(['prop1__type1']);
+    });
+
+    afterEach(function() {
+      App.config.getPropertiesFromTheme.restore();
+    });
+
+    it("add skipped config", function() {
+      var configuration = {
+        properties: {
+          prop1: 'val1'
+        },
+        tag: 'tag1',
+        type: 'type1',
+        version: '1'
+      };
+      var serviceVersionMap = {v1: {}};
+      mixin.addCompareCSConfigs(configuration, serviceVersionMap, {service_config_version: 'v1'});
+      expect(serviceVersionMap).to.be.eql({
+        v1: {
+          'prop1-type1': {
+            name: 'prop1',
+            value: 'val1',
+            type: 'type1',
+            tag: 'tag1',
+            version: '1',
+            service_config_version: 'v1'
+          },
+         'type1-type1': {
+           name: 'type1',
+           value: '',
+           type: 'type1',
+           tag: 'tag1',
+           version: '1',
+           service_config_version: 'v1'
+         }
+        }
+      });
+    });
+
+    it("add config", function() {
+      var configuration = {
+        properties: {
+          prop2: 'val2'
+        },
+        tag: 'tag1',
+        type: 'type1',
+        version: '1'
+      };
+      var serviceVersionMap = {v1: {}};
+      mixin.addCompareCSConfigs(configuration, serviceVersionMap, {service_config_version: 'v1'});
+      expect(serviceVersionMap).to.be.eql({
+        v1: {
+          'type1-type1': {
+            name: 'type1',
+            value: 'prop2=val2\n',
+            type: 'type1',
+            tag: 'tag1',
+            version: '1',
+            service_config_version: 'v1'
+          }
+        }
+      });
+    });
+  });
+
+  describe("#setCompareConfigs()", function () {
+
+    beforeEach(function() {
+      sinon.stub(App.config, 'getConfigTagFromFileName').returns('file1');
+      sinon.stub(mixin, 'getComparisonConfig', function(serviceConfig) {
+        return serviceConfig;
+      });
+      sinon.stub(mixin, 'hasCompareDiffs').returns(false);
+      sinon.stub(mixin, 'getMockComparisonConfig').returns({name: 'mock'});
+    });
+
+    afterEach(function() {
+      App.config.getConfigTagFromFileName.restore();
+      mixin.getComparisonConfig.restore();
+      mixin.hasCompareDiffs.restore();
+      mixin.getMockComparisonConfig.restore();
+    });
+
+    it("compare current with selected", function() {
+      var serviceConfig = Em.Object.create({
+        name: 'c1'
+      });
+      var serviceVersionMap = {
+        'v1': {
+          'c1-file1': {
+            name: 'c1'
+          }
+        },
+        'v2': {
+          'c1-file1': {
+            name: 'c1'
+          }
+        }
+      };
+      mixin.setCompareConfigs(serviceConfig, serviceVersionMap, 'v1', 'v2');
+      expect(serviceConfig.get('compareConfigs').mapProperty('name')).to.be.eql(['c1', 'c1']);
+      expect(serviceConfig.get('hasCompareDiffs')).to.be.false;
+    });
+
+    it("compare current with mock selected", function() {
+      var serviceConfig = Em.Object.create({
+        name: 'c1'
+      });
+      var serviceVersionMap = {
+        'v1': {
+          'c1-file1': {
+            name: 'c1'
+          }
+        },
+        'v2': {}
+      };
+      mixin.setCompareConfigs(serviceConfig, serviceVersionMap, 'v1', 'v2');
+      expect(serviceConfig.get('compareConfigs').mapProperty('name')).to.be.eql(['c1', 'mock']);
+      expect(serviceConfig.get('hasCompareDiffs')).to.be.true;
+    });
+
+    it("compare mock current with selected", function() {
+      var serviceConfig = Em.Object.create({
+        name: 'c1'
+      });
+      var serviceVersionMap = {
+        'v1': {},
+        'v2': {
+          'c1-file1': {
+            name: 'c1'
+          }
+        }
+      };
+      mixin.setCompareConfigs(serviceConfig, serviceVersionMap, 'v1', 'v2');
+      expect(serviceConfig.get('compareConfigs').mapProperty('name')).to.be.eql(['mock', 'c1']);
+      expect(serviceConfig.get('hasCompareDiffs')).to.be.true;
+    });
+  });
+
+  describe("#getMockComparisonConfig()", function () {
+
+    beforeEach(function() {
+      sinon.stub(App.ServiceConfigVersion, 'find').returns({});
+      sinon.stub(App.ServiceConfigProperty, 'create', function(object) {
+        return object;
+      });
+    });
+
+    afterEach(function() {
+      App.ServiceConfigVersion.find.restore();
+      App.ServiceConfigProperty.create.restore();
+    });
+
+    it("should return mock config object", function() {
+      var serviceConfig = Em.Object.create();
+      mixin.set('content.serviceName', 'S1');
+      expect(mixin.getMockComparisonConfig(serviceConfig, 'v2')).to.be.eql(Em.Object.create({
+        "isComparison": false,
+        "isInstance": true,
+        "isDestroyed": false,
+        "isDestroying": false,
+        "isObserverable": true,
+        "isEditable": false,
+        "serviceVersion": {},
+        "isMock": true,
+        "displayType": "label",
+        "value": "Undefined"
+      }));
+      expect(App.ServiceConfigVersion.find.calledWith('S1_v2')).to.be.true;
+    });
+  });
+
+  describe("#getComparisonConfig()", function () {
+
+    beforeEach(function() {
+      sinon.stub(App.ServiceConfigVersion, 'find').returns({});
+      sinon.stub(App.ServiceConfigProperty, 'create', function(object) {
+        return object;
+      });
+      sinon.stub(App.config, 'formatPropertyValue').returns('val');
+    });
+
+    afterEach(function() {
+      App.ServiceConfigVersion.find.restore();
+      App.ServiceConfigProperty.create.restore();
+      App.config.formatPropertyValue.restore();
+    });
+
+    it("should return comparison config object", function() {
+      var serviceConfig = Em.Object.create();
+      var compareConfig = {service_config_version: 'v2', isFinal: false};
+      mixin.set('content.serviceName', 'S1');
+
+      expect(mixin.getComparisonConfig(serviceConfig, compareConfig)).to.be.eql(Em.Object.create({
+        "isComparison": false,
+        "isOriginalSCP": false,
+        "isInstance": true,
+        "isDestroyed": false,
+        "isDestroying": false,
+        "isObserverable": true,
+        "isEditable": false,
+        "serviceVersion": {},
+        "isFinal": false,
+        "value": "val",
+        "compareConfigs": null
+      }));
+      expect(App.ServiceConfigVersion.find.calledWith('S1_v2')).to.be.true;
+    });
+
+    it("serviceConfig is Mock", function() {
+      var serviceConfig = Em.Object.create({isMock: true});
+      var compareConfig = {service_config_version: 'v2', isFinal: false};
+      mixin.set('content.serviceName', 'S1');
+
+      expect(mixin.getComparisonConfig(serviceConfig, compareConfig)).to.be.eql(Em.Object.create({
+        "isComparison": false,
+        "isOriginalSCP": false,
+        "isMock": false,
+        "isInstance": true,
+        "isDestroyed": false,
+        "isDestroying": false,
+        "isObserverable": true,
+        "isEditable": false,
+        "displayType": "string",
+        "serviceVersion": {},
+        "isFinal": false,
+        "value": "val",
+        "compareConfigs": null
+      }));
+      expect(App.ServiceConfigVersion.find.calledWith('S1_v2')).to.be.true;
+    });
+
+    it("compareConfig is null", function() {
+      var serviceConfig = Em.Object.create({isMock: true});
+      mixin.set('content.serviceName', 'S1');
+
+      expect(mixin.getComparisonConfig(serviceConfig, null)).to.be.eql(Em.Object.create({
+        "isComparison": false,
+        "isOriginalSCP": false,
+        "isMock": true,
+        "isInstance": true,
+        "isDestroyed": false,
+        "isDestroying": false,
+        "isObserverable": true,
+        "isEditable": false
+      }));
+      expect(App.ServiceConfigVersion.find.called).to.be.false;
+    });
+  });
+
+  describe("#setCompareDefaultGroupConfig()", function () {
+
+    beforeEach(function() {
+      sinon.stub(mixin, 'getComparisonConfig').returns({name: 'c1'});
+      sinon.stub(mixin, 'getMockComparisonConfig').returns({name: 'mock'});
+      sinon.stub(mixin, 'hasCompareDiffs').returns(true);
+    });
+
+    afterEach(function() {
+      mixin.getComparisonConfig.restore();
+      mixin.getMockComparisonConfig.restore();
+      mixin.hasCompareDiffs.restore()
+    });
+
+    it("compareConfig correct, isMock=true", function() {
+      var serviceConfig = Em.Object.create({
+        isMock: true
+      });
+      expect(mixin.setCompareDefaultGroupConfig(serviceConfig, {})).to.be.eql(Em.Object.create({
+        "isMock": true,
+        "compareConfigs": [
+          {name: 'c1'}
+        ],
+        "isComparison": true,
+        "hasCompareDiffs": true
+      }));
+    });
+
+    it("compareConfig correct, isMock=false", function() {
+      var serviceConfig = Em.Object.create({
+        isMock: false
+      });
+      expect(mixin.setCompareDefaultGroupConfig(serviceConfig, {})).to.be.eql(Em.Object.create({
+        "isMock": false,
+        "compareConfigs": [
+          {name: 'c1'}
+        ],
+        "isComparison": true,
+        "hasCompareDiffs": true
+      }));
+    });
+
+    it("compareConfig is null, isUserProperty=true", function() {
+      var serviceConfig = Em.Object.create({
+        isUserProperty: true
+      });
+      expect(mixin.setCompareDefaultGroupConfig(serviceConfig, null)).to.be.eql(Em.Object.create({
+        "isUserProperty": true,
+        "compareConfigs": [
+          {
+            "name": "mock"
+          }
+        ],
+        "isComparison": true,
+        "hasCompareDiffs": true
+      }));
+    });
+
+    it("compareConfig is null, isUserProperty=false", function() {
+      var serviceConfig = Em.Object.create({
+        isUserProperty: false,
+        isRequiredByAgent: true
+      });
+      expect(mixin.setCompareDefaultGroupConfig(serviceConfig, null)).to.be.eql(Em.Object.create({
+        "isUserProperty": false,
+        "isRequiredByAgent": true,
+        "compareConfigs": [
+          {
+            "name": "mock"
+          }
+        ],
+        "isComparison": true,
+        "hasCompareDiffs": true
+      }));
+    });
+  });
+
+  describe("#hasCompareDiffs()", function () {
+
+    var testCases = [
+      {
+        originalConfig: Em.Object.create({
+          displayType: 'password'
+        }),
+        compareConfig: Em.Object.create({
+        }),
+        title: 'original config is password',
+        expected: false
+      },
+      {
+        originalConfig: Em.Object.create({
+          value: [{}]
+        }),
+        compareConfig: Em.Object.create({
+          value: [{}]
+        }),
+        title: 'has equal Array values',
+        expected: false
+      },
+      {
+        originalConfig: Em.Object.create({
+          value: Em.A([{}])
+        }),
+        compareConfig: Em.Object.create({
+          value: Em.A([{}])
+        }),
+        title: 'has equal Em.A() values',
+        expected: false
+      },
+      {
+        originalConfig: Em.Object.create({
+          value: [Em.Object.create({value: 'val1'})]
+        }),
+        compareConfig: Em.Object.create({
+          value: [Em.Object.create({value: 'val2'})]
+        }),
+        title: 'has equal Em.A() values',
+        expected: true
+      },
+      {
+        originalConfig: Em.Object.create({
+          value: [Em.Object.create({value: 'val1', isFinal: true})]
+        }),
+        compareConfig: Em.Object.create({
+          value: [Em.Object.create({value: 'val1', isFinal: false})]
+        }),
+        title: 'has equal Em.A() values',
+        expected: true
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it(test.title, function() {
+        expect(mixin.hasCompareDiffs(test.originalConfig, test.compareConfig)).to.be.equal(test.expected);
+      });
+    });
+  });
+
+  describe("#getMockConfig()", function () {
+
+    beforeEach(function() {
+      sinon.stub(App.ServiceConfigProperty, 'create', function(config) {
+        return config;
+      });
+      sinon.stub(App.config, 'getDefaultCategory').returns({});
+      this.mock = sinon.stub(App.configsCollection, 'getConfigByName');
+    });
+
+    afterEach(function() {
+      App.ServiceConfigProperty.create.restore();
+      App.config.getDefaultCategory.restore();
+      App.configsCollection.getConfigByName.restore();
+    });
+
+    it("get config from collection", function() {
+      this.mock.returns({name: 'c1'});
+      expect(mixin.getMockConfig('c1', 'S1', 'f1')).to.be.eql({
+        name: 'c1'
+      });
+    });
+
+    it("get mock config", function() {
+      this.mock.returns(null);
+      expect(mixin.getMockConfig('c1', 'S1', 'f1')).to.be.eql({
+        description: 'c1',
+        displayName: 'c1',
+        isOverridable: false,
+        isReconfigurable: false,
+        isRequired: false,
+        isRequiredByAgent: true,
+        isSecureConfig: false,
+        isUserProperty: true,
+        isVisible: true,
+        isOriginalSCP: false,
+        name: 'c1',
+        filename: 'f1',
+        serviceName: 'S1',
+        category: {},
+        value: Em.I18n.t('common.property.undefined'),
+        isMock: true,
+        displayType: 'label'
+      });
+    });
+  });
+
+  describe("#getCompareVersionConfigs()", function () {
+
+    it("App.ajax.send should be called", function() {
+      mixin.set('content.serviceName', 'S1');
+      mixin.getCompareVersionConfigs('v2');
+      expect(testHelpers.findAjaxRequest('name', 'service.serviceConfigVersions.get.multiple')[0]).to.eql({
+        name: 'service.serviceConfigVersions.get.multiple',
+        sender: mixin,
+        data: {
+          serviceName: 'S1',
+          serviceConfigVersions: 'v2'
+        }
+      });
+      expect(mixin.get('versionLoaded')).to.be.false;
+    });
+  });
+});
+


Mime
View raw message