ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From onechipore...@apache.org
Subject ambari git commit: AMBARI-18177. [UI] Atlas Zookeeper properties should be updated on zookeeper add/remove operations (onechiporenko)
Date Wed, 14 Sep 2016 13:25:00 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 acdde3d5a -> 468589ae7


AMBARI-18177. [UI] Atlas Zookeeper properties should be updated on zookeeper add/remove operations
(onechiporenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/468589ae
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/468589ae
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/468589ae

Branch: refs/heads/branch-2.5
Commit: 468589ae7b2854a7e5fc98790a20dc45e2c7d96c
Parents: acdde3d
Author: Oleg Nechiporenko <onechiporenko@apache.org>
Authored: Wed Aug 17 11:11:06 2016 +0300
Committer: Oleg Nechiporenko <onechiporenko@apache.org>
Committed: Wed Sep 14 16:24:54 2016 +0300

----------------------------------------------------------------------
 ambari-web/app/controllers/main/host/details.js |  20 +-
 .../configs/add_component_config_initializer.js |  28 +-
 .../app/utils/configs/config_initializer.js     |   4 +-
 .../configs/hosts_based_initializer_mixin.js    |   3 +-
 .../admin/kerberos/step1_controller_test.js     |  10 +-
 .../test/controllers/main/host/details_test.js  |  50 ++
 .../test/utils/configs_collection_test.js       | 136 +++--
 .../common/widget/graph_widget_view_test.js     | 552 ++++++++++++++++++-
 8 files changed, 728 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index 1364adf..2076333 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -774,6 +774,7 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow
   updateZkConfigs: function (configs) {
     var portValue = configs['zoo.cfg'] && Em.get(configs['zoo.cfg'], 'clientPort');
     var zkPort = typeof portValue === 'undefined' ? '2181' : portValue;
+    var infraSolrZnode = configs['infra-solr-env'] ? Em.get(configs['infra-solr-env'], 'infra_solr_znode')
: '/ambari-solr';
     var initializer = App.AddZooKeeperComponentsInitializer;
     var hostComponentsTopology = {
       masterComponentHosts: []
@@ -788,7 +789,8 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow
       }
     }
     var dependencies = {
-      zkClientPort: zkPort
+      zkClientPort: zkPort,
+      infraSolrZnode: infraSolrZnode
     };
     hostComponentsTopology.masterComponentHosts = masterComponents;
     Em.keys(configs).forEach(function(fileName) {
@@ -1337,6 +1339,10 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow
     if (services.someProperty('serviceName', 'KAFKA')) {
       urlParams.push('(type=kafka-broker&tag=' + data.Clusters.desired_configs['kafka-broker'].tag
+ ')');
     }
+    if (services.someProperty('serviceName', 'ATLAS')) {
+      urlParams.push('(type=application-properties&tag=' + data.Clusters.desired_configs['application-properties'].tag
+ ')');
+      urlParams.push('(type=infra-solr-env&tag=' + data.Clusters.desired_configs['infra-solr-env'].tag
+ ')');
+    }
     return urlParams;
   },
 
@@ -1415,6 +1421,18 @@ App.MainHostDetailsController = Em.Controller.extend(App.SupportClientConfigsDow
         }
       );
     }
+    if (installedServiceNames.contains('ATLAS')) {
+      groups.push(
+        {
+          properties: {
+            'application-properties': configs['application-properties']
+          },
+          properties_attributes: {
+            'application-properties': attributes['application-properties']
+          }
+        }
+      );
+    }
     this.saveConfigsBatch(groups, 'ZOOKEEPER_SERVER');
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/app/utils/configs/add_component_config_initializer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/add_component_config_initializer.js b/ambari-web/app/utils/configs/add_component_config_initializer.js
index 6a8ab4c..7e3fedf 100644
--- a/ambari-web/app/utils/configs/add_component_config_initializer.js
+++ b/ambari-web/app/utils/configs/add_component_config_initializer.js
@@ -59,7 +59,10 @@ App.AddComponentConfigInitializer = App.HaConfigInitializerClass.extend(App.Host
       'nimbus.seeds': this.getHostsListComponentJSONStringifiedConfig('NIMBUS', true),
       'hadoop.proxyuser.{{webhcatUser}}.hosts': this.getComponentsHostsConfig(['HIVE_SERVER',
'WEBHCAT_SERVER', 'HIVE_METASTORE'], false, true),
       'hadoop.proxyuser.{{hiveUser}}.hosts': this.getComponentsHostsConfig(['HIVE_SERVER',
'WEBHCAT_SERVER', 'HIVE_METASTORE'], false, true),
-      'hive.metastore.uris': this.getHostsWithPortConfig(['HIVE_METASTORE'], 'thrift://',
'', ',thrift://', 'hiveMetastorePort', true)
+      'hive.metastore.uris': this.getHostsWithPortConfig(['HIVE_METASTORE'], 'thrift://',
'', ',thrift://', 'hiveMetastorePort', true),
+      'atlas.audit.hbase.zookeeper.quorum': this.getHostsListComponentConfig('ZOOKEEPER_SERVER',
true),
+      'atlas.graph.storage.hostname': this.getHostsListComponentConfig('ZOOKEEPER_SERVER',
true),
+      'atlas.kafka.zookeeper.connect': this.getHostsWithPortConfig('ZOOKEEPER_SERVER', '',
'', ',', 'zkClientPort', true)
     };
   },
 
@@ -72,7 +75,8 @@ App.AddComponentConfigInitializer = App.HaConfigInitializerClass.extend(App.Host
    */
   __defaultUniqueInitializers: {
     'yarn.resourcemanager.zk-address': '_initYarnRMZkAdress',
-    'templeton.hive.properties': '_initTempletonHiveProperties'
+    'templeton.hive.properties': '_initTempletonHiveProperties',
+    'atlas.graph.index.search.solr.zookeeper-url': '_initAtlasGraphIndexSearchSolrZkUrl'
   },
 
   /**
@@ -238,6 +242,20 @@ App.AddComponentConfigInitializer = App.HaConfigInitializerClass.extend(App.Host
     return configProperty;
   },
 
+  _initAtlasGraphIndexSearchSolrZkUrl: function (configProperty, localDB, dependencies, initializer)
{
+    var solr = dependencies.infraSolrZnode;
+    return this._initAsHostsWithPort(configProperty, localDB, dependencies, {
+      component: 'ZOOKEEPER_SERVER',
+      componentExists: true,
+      modifier: {
+        prefix: '',
+        suffix: solr,
+        delimiter: solr + ','
+      },
+      portKey: 'zkClientPort'
+    });
+  },
+
   /**
    * Set up `this.initializers` and `this.uniqueInitializers` properties according
    * to property list names.
@@ -282,7 +300,11 @@ App.AddZooKeeperComponentsInitializer = App.AddComponentConfigInitializer.create
     'yarn.resourcemanager.zk-address',
     'hive.zookeeper.quorum',
     'storm.zookeeper.servers',
-    'hadoop.registry.zk.quorum'
+    'hadoop.registry.zk.quorum',
+    'atlas.audit.hbase.zookeeper.quorum',
+    'atlas.graph.index.search.solr.zookeeper-url',
+    'atlas.graph.storage.hostname',
+    'atlas.kafka.zookeeper.connect'
   ]
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/app/utils/configs/config_initializer.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/config_initializer.js b/ambari-web/app/utils/configs/config_initializer.js
index c8a4cef..cb5b41f 100644
--- a/ambari-web/app/utils/configs/config_initializer.js
+++ b/ambari-web/app/utils/configs/config_initializer.js
@@ -174,9 +174,9 @@ App.ConfigInitializer = App.ConfigInitializerClass.create(App.MountPointsBasedIn
   _initHiveDatabaseValue: function (configProperty) {
     var newMySQLDBOption = Em.get(configProperty, 'options').findProperty('displayName',
'New MySQL Database');
     if (newMySQLDBOption) {
-      var isNewMySQLDBOptionHidden = !App.get('supports.alwaysEnableManagedMySQLForHive')
&& App.get('router.currentState.name') != 'configs' &&
+      var isNewMySQLDBOptionHidden = !App.get('supports.alwaysEnableManagedMySQLForHive')
&& App.get('router.currentState.name') !== 'configs' &&
         !App.get('isManagedMySQLForHiveEnabled');
-      if (isNewMySQLDBOptionHidden && Em.get(configProperty, 'value') == 'New MySQL
Database') {
+      if (isNewMySQLDBOptionHidden && Em.get(configProperty, 'value') === 'New MySQL
Database') {
         Em.set(configProperty, 'value', 'Existing MySQL Database');
       }
       Em.set(newMySQLDBOption, 'hidden', isNewMySQLDBOptionHidden);

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js b/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
index 5c51c12..d0d2503 100644
--- a/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
+++ b/ambari-web/app/utils/configs/hosts_based_initializer_mixin.js
@@ -118,9 +118,8 @@ App.HostsBasedInitializerMixin = Em.Mixin.create({
       var hasFound = initializer.components.contains(masterComponent.component);
       if (Em.isNone(initializer.isInstalled)) {
         return hasFound;
-      } else {
-        return hasFound && masterComponent.isInstalled === initializer.isInstalled;
       }
+      return hasFound && masterComponent.isInstalled === initializer.isInstalled;
     }).sortProperty('hostName').mapProperty('hostName');
     if (!initializer.asArray) {
       hostNames = hostNames.uniq().join(',');

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/test/controllers/main/admin/kerberos/step1_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/admin/kerberos/step1_controller_test.js b/ambari-web/test/controllers/main/admin/kerberos/step1_controller_test.js
index a90fa72..9280367f 100644
--- a/ambari-web/test/controllers/main/admin/kerberos/step1_controller_test.js
+++ b/ambari-web/test/controllers/main/admin/kerberos/step1_controller_test.js
@@ -34,14 +34,8 @@ describe('App.KerberosWizardStep1Controller', function() {
     it("test", function() {
       var options=controller.get('options');
       controller.propertyDidChange('selectedOption');
-      options.forEach(function(option) {
-        if (option.value === controller.get('selectedItem')) {
-          var preConditions=option.preConditions;
-          preConditions.forEach(function(condition) {
-            expect(condition.get('checked')).to.be.false;
-          });
-        }          
-      }, this);
+      var option = options.findProperty('value', controller.get('selectedItem'));
+      expect(option.preConditions.everyProperty('checked', false)).to.be.true;
     });
     
   });

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/test/controllers/main/host/details_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js
index 71efbae..154d0b2 100644
--- a/ambari-web/test/controllers/main/host/details_test.js
+++ b/ambari-web/test/controllers/main/host/details_test.js
@@ -1369,6 +1369,56 @@ describe('App.MainHostDetailsController', function () {
             }
           }
         }
+      },
+      {
+        m: 'ATLAS configs',
+        hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+        configs: {
+          'application-properties': {
+            'atlas.audit.hbase.zookeeper.quorum': '',
+            'atlas.graph.index.search.solr.zookeeper-url': '',
+            'atlas.graph.storage.hostname': '',
+            'atlas.kafka.zookeeper.connect': ''
+          }
+        },
+        e: {
+          configs: {
+            'application-properties': {
+              'atlas.audit.hbase.zookeeper.quorum': 'host1,host2',
+              'atlas.graph.index.search.solr.zookeeper-url': 'host1:2181/ambari-solr,host2:2181/ambari-solr',
+              'atlas.graph.storage.hostname': 'host1,host2',
+              'atlas.kafka.zookeeper.connect': 'host1:2181,host2:2181'
+            }
+          }
+        }
+      },
+      {
+        m: 'ATLAS configs with custom solr',
+        hostComponentModel: makeHostComponentModel('ZOOKEEPER_SERVER', ['host1', 'host2']),
+        configs: {
+          'infra-solr-env': {
+            'infra_solr_znode': '/custom-solr'
+          },
+          'application-properties': {
+            'atlas.audit.hbase.zookeeper.quorum': '',
+            'atlas.graph.index.search.solr.zookeeper-url': '',
+            'atlas.graph.storage.hostname': '',
+            'atlas.kafka.zookeeper.connect': ''
+          }
+        },
+        e: {
+          configs: {
+            'infra-solr-env': {
+              'infra_solr_znode': '/custom-solr'
+            },
+            'application-properties': {
+              'atlas.audit.hbase.zookeeper.quorum': 'host1,host2',
+              'atlas.graph.index.search.solr.zookeeper-url': 'host1:2181/custom-solr,host2:2181/custom-solr',
+              'atlas.graph.storage.hostname': 'host1,host2',
+              'atlas.kafka.zookeeper.connect': 'host1:2181,host2:2181'
+            }
+          }
+        }
       }
     ];
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/test/utils/configs_collection_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/configs_collection_test.js b/ambari-web/test/utils/configs_collection_test.js
index bd97950..4a76ae9 100644
--- a/ambari-web/test/utils/configs_collection_test.js
+++ b/ambari-web/test/utils/configs_collection_test.js
@@ -34,29 +34,32 @@ describe('App.configsCollection', function () {
 
   describe('#add', function () {
 
-    var cases = [
+    var throwCases = [
       {
+        obj: undefined,
         collection: [],
-        isError: false,
-        title: 'initial state'
+        isError: true,
+        title: 'null passed'
       },
       {
-        obj: undefined,
+        obj: {},
         collection: [],
         isError: true,
-        title: 'no item passed'
+        title: 'no id passed'
       },
       {
         obj: undefined,
         collection: [],
         isError: true,
-        title: 'null passed'
-      },
+        title: 'no item passed'
+      }
+    ];
+
+    var cases = [
       {
-        obj: {},
         collection: [],
-        isError: true,
-        title: 'no id passed'
+        isError: false,
+        title: 'initial state'
       },
       {
         obj: {
@@ -114,20 +117,22 @@ describe('App.configsCollection', function () {
       }
     ];
 
+    throwCases.forEach(function (item) {
+
+      it(item.title, function () {
+        expect(function () {configsCollection.add(item.obj);}).to.throw(Error);
+      });
+
+    });
+
     cases.forEach(function (item) {
 
       describe(item.title, function () {
 
         beforeEach(function () {
-          try {
-            if (item.hasOwnProperty('obj')) {
-              configsCollection.add(item.obj);
-            }
-          } catch (e) {}
-        });
-
-        it('thrown error', function () {
-          expect(Em.assert.threw()).to.equal(item.isError);
+          if (item.hasOwnProperty('obj')) {
+            configsCollection.add(item.obj);
+          }
         });
 
         it('configs array', function () {
@@ -148,7 +153,7 @@ describe('App.configsCollection', function () {
 
   describe('#getConfig', function () {
 
-    var cases = [
+    var throwCases = [
       {
         result: undefined,
         isError: true,
@@ -159,7 +164,10 @@ describe('App.configsCollection', function () {
         result: undefined,
         isError: true,
         title: 'invalid id passed'
-      },
+      }
+    ];
+
+    var cases = [
       {
         id: 1,
         result: {
@@ -184,6 +192,17 @@ describe('App.configsCollection', function () {
       }
     ];
 
+    throwCases.forEach(function (item) {
+
+      it(item.title, function () {
+        configsCollection.add({
+          id: 1
+        });
+        expect(function () {configsCollection.getConfig(item.id);}).to.throw(Error);
+      });
+
+    });
+
     cases.forEach(function (item) {
 
       describe(item.title, function () {
@@ -194,13 +213,7 @@ describe('App.configsCollection', function () {
           configsCollection.add({
             id: 1
           });
-          try {
-            result = configsCollection.getConfig(item.id);
-          } catch (e) {}
-        });
-
-        it('thrown error', function () {
-          expect(Em.assert.threw()).to.equal(item.isError);
+          result = configsCollection.getConfig(item.id);
         });
 
         it('returned value', function () {
@@ -215,20 +228,22 @@ describe('App.configsCollection', function () {
 
   describe('#getConfigByName', function () {
 
-    var configIds = ['n0_f0', 'n1_f1'],
-      cases = [
-        {
-          fileName: 'f0',
-          result: undefined,
-          isError: true,
-          title: 'no name passed'
-        },
-        {
-          name: 'n0',
-          result: undefined,
-          isError: true,
-          title: 'no filename passed'
-        },
+    var configIds = ['n0_f0', 'n1_f1'];
+    var throwCases = [
+      {
+        fileName: 'f0',
+        result: undefined,
+        isError: true,
+        title: 'no name passed'
+      },
+      {
+        name: 'n0',
+        result: undefined,
+        isError: true,
+        title: 'no filename passed'
+      }
+    ];
+    var cases = [
         {
           name: 'n0',
           fileName: 'f0',
@@ -247,6 +262,25 @@ describe('App.configsCollection', function () {
         }
       ];
 
+    beforeEach(function () {
+      sinon.stub(App.config, 'configId', function (name, fileName) {
+        return name + '_' + fileName;
+      });
+    });
+
+    afterEach(function () {
+      configsCollection.clearAll();
+      App.config.configId.restore();
+    });
+
+    throwCases.forEach(function (item) {
+
+      it(item.title, function () {
+        expect(function () {configsCollection.getConfigByName(item.name, item.fileName);}).to.throw(Error);
+      });
+
+    });
+
     cases.forEach(function (item) {
 
       describe(item.title, function () {
@@ -254,27 +288,13 @@ describe('App.configsCollection', function () {
         var result;
 
         beforeEach(function () {
-          sinon.stub(App.config, 'configId', function (name, fileName) {
-            return name + '_' + fileName;
-          });
+
           configIds.forEach(function (id) {
             configsCollection.add({
               id: id
             });
           });
-          try {
-            result = configsCollection.getConfigByName(item.name, item.fileName);
-          } catch (e) {}
-        });
-
-        afterEach(function () {
-          App.config.configId.restore();
-          configsCollection.clearAll();
-        });
-
-
-        it('thrown error', function () {
-          expect(Em.assert.threw()).to.equal(item.isError);
+          result = configsCollection.getConfigByName(item.name, item.fileName);
         });
 
         it('returned value', function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/468589ae/ambari-web/test/views/common/widget/graph_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/widget/graph_widget_view_test.js b/ambari-web/test/views/common/widget/graph_widget_view_test.js
index 31c9db0..70fcafb 100644
--- a/ambari-web/test/views/common/widget/graph_widget_view_test.js
+++ b/ambari-web/test/views/common/widget/graph_widget_view_test.js
@@ -25,7 +25,12 @@ describe('App.GraphWidgetView', function () {
   var view;
 
   beforeEach(function () {
-    view = App.GraphWidgetView.create();
+    view = App.GraphWidgetView.create({
+      content: Em.Object.create({
+        properties: {}
+      }),
+      parentView: Em.Object.create()
+    });
   });
 
   afterEach(function () {
@@ -272,4 +277,549 @@ describe('App.GraphWidgetView', function () {
     });
   });
 
+  describe("#timeRange()", function () {
+    var testCases = [
+      {
+        time_range: null,
+        currentTimeIndex: 1,
+        customTimeRange: null,
+        expected: 3600
+      },
+      {
+        time_range: null,
+        currentTimeIndex: 1,
+        customTimeRange: 2,
+        expected: 2
+      },
+      {
+        time_range: null,
+        currentTimeIndex: 8,
+        customTimeRange: 2,
+        expected: 0
+      },
+      {
+        time_range: 2,
+        currentTimeIndex: 1,
+        customTimeRange: null,
+        expected: 7200
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("time_range=" + test.time_range +
+         " currentTimeIndex=" + test.currentTimeIndex +
+         " customTimeRange=" + test.customTimeRange, function() {
+        view.set('content.properties.time_range', test.time_range);
+        view.set('customTimeRange', test.customTimeRange);
+        view.reopen({
+          exportTargetView: Em.Object.create({
+            currentTimeIndex: test.currentTimeIndex
+          })
+        });
+        view.propertyDidChange('timeRange');
+        expect(view.get('timeRange')).to.be.equal(test.expected);
+      });
+    });
+  });
+
+  describe("#drawWidget()", function () {
+
+    beforeEach(function() {
+      sinon.stub(view, 'calculateValues').returns({});
+      view.set('data', null);
+    });
+
+    afterEach(function() {
+      view.calculateValues.restore();
+    });
+
+    it("isLoaded = false", function() {
+      view.set('isLoaded', false);
+      view.drawWidget();
+      expect(view.get('data')).to.be.null;
+    });
+
+    it("isLoaded = true", function() {
+      view.set('isLoaded', true);
+      view.drawWidget();
+      expect(view.get('data')).to.be.eql({});
+    });
+  });
+
+  describe("#calculateValues()", function () {
+    beforeEach(function() {
+      this.mockExtract = sinon.stub(view, 'extractExpressions');
+      this.mockCompute = sinon.stub(view, 'computeExpression');
+    });
+
+    afterEach(function() {
+      this.mockExtract.restore();
+      this.mockCompute.restore();
+    });
+
+    var testCases = [
+      {
+        metrics: {},
+        values: [],
+        expression: [],
+        computed: {},
+        expected: []
+      },
+      {
+        metrics: {},
+        values: [{}],
+        expression: [],
+        computed: {},
+        expected: []
+      },
+      {
+        metrics: {},
+        values: [{
+          value: '${m1}'
+        }],
+        expression: ['${m1}'],
+        computed: {
+          '${m1}': []
+        },
+        expected: []
+      },
+      {
+        metrics: {},
+        values: [{
+          value: '${m1}',
+          name: 'v1'
+        }],
+        expression: ['${m1}'],
+        computed: {
+          '${m1}': [{
+            m1: {}
+          }]
+        },
+        expected: [
+          {
+            name: 'v1',
+            data: [{
+              m1: {}
+            }]
+          }
+        ]
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("metrics=" + JSON.stringify(test.metrics) +
+         " values=" + JSON.stringify(test.values) +
+         " expression=" + test.expression +
+         " computed=" + test.computed, function() {
+        view.set('metrics', test.metrics);
+        view.set('content.values', test.values);
+        this.mockCompute.returns(test.computed);
+        this.mockExtract.returns(test.expression);
+        expect(view.calculateValues()).to.be.eql(test.expected);
+      });
+    });
+  });
+
+  describe("#computeExpression()", function () {
+
+    beforeEach(function() {
+      sinon.stub(view, 'adjustData', function (dataLinks) {
+        dataLinks.m1[1] = [3, 1112];
+      });
+    });
+
+    afterEach(function() {
+      view.adjustData.restore();
+    });
+
+    var testCases = [
+      {
+        expression: '1',
+        metrics: [],
+        expected: {
+          '${1}': []
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1',
+        metrics: [],
+        expected: {
+          '${m1}': []
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1',
+        metrics: [{
+          name: 'm1',
+          data: []
+        }],
+        expected: {
+          '${m1}': []
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1',
+        metrics: [{
+          name: 'm1',
+          data: [
+            [null, 1111]
+          ]
+        }],
+        expected: {
+          '${m1}': [
+            [null, 1111]
+          ]
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1',
+        metrics: [{
+          name: 'm1',
+          data: [
+            [1, 1111]
+          ]
+        }],
+        expected: {
+          '${m1}': [
+            [1, 1111]
+          ]
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1+1',
+        metrics: [{
+          name: 'm1',
+          data: [
+            [1, 1111]
+          ]
+        }],
+        expected: {
+          '${m1+1}': [
+            [2, 1111]
+          ]
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1/m2',
+        metrics: [
+          {
+            name: 'm1',
+            data: [
+              [0, 1111]
+            ]
+          },
+          {
+            name: 'm2',
+            data: [
+              [0, 1111]
+            ]
+          }
+        ],
+        expected: {
+          '${m1/m2}': [
+            [0, 1111]
+          ]
+        },
+        adjustDataCalled: false
+      },
+      {
+        expression: 'm1+m2',
+        metrics: [
+          {
+            name: 'm1',
+            data: [
+              [1, 1111]
+            ]
+          },
+          {
+            name: 'm2',
+            data: [
+              [1, 1111],
+              [2, 1112]
+            ]
+          }],
+        expected: {
+          '${m1+m2}': [
+            [2, 1111],
+            [5, 1112]
+          ]
+        },
+        adjustDataCalled: true
+      }
+    ];
+
+    testCases.forEach(function(test) {
+      it("expression=" + test.expression +
+         " metrics=" + JSON.stringify(test.metrics), function() {
+        expect(view.computeExpression(test.expression, test.metrics)).to.be.eql(test.expected);
+        expect(view.adjustData.calledOnce).to.be.equal(test.adjustDataCalled);
+      });
+    });
+  });
+
+  describe("#addTimeProperties()", function () {
+
+    beforeEach(function() {
+      sinon.stub(App, 'dateTime').returns(10000);
+      view.set('timeStep', 15);
+    });
+
+    afterEach(function() {
+      App.dateTime.restore();
+    });
+
+    it("targetView is null", function() {
+      view.reopen({
+        exportTargetView: null
+      });
+      view.set('parentView', null);
+      expect(view.addTimeProperties([{}])).to.be.empty;
+    });
+
+    it("empty metricPaths", function() {
+      expect(view.addTimeProperties([])).to.be.empty;
+    });
+
+    it("timeRange=5", function() {
+      view.reopen({
+        timeRange: 5,
+        exportTargetView: Em.Object.create({
+          isPopup: true
+        })
+      });
+      expect(view.addTimeProperties(['m1'])).to.be.eql([
+        "m1[5,10,15]"
+      ]);
+    });
+
+    it("timeRange=0, customStartTime=null", function() {
+      view.reopen({
+        timeRange: 0,
+        exportTargetView: Em.Object.create({
+          isPopup: true,
+          customStartTime: null
+        })
+      });
+      expect(view.addTimeProperties(['m1'])).to.be.eql([
+        "m1[10,10,15]"
+      ]);
+    });
+
+    it("timeRange=0, customStartTime=1000, customEndTime=null", function() {
+      view.reopen({
+        timeRange: 0,
+        exportTargetView: Em.Object.create({
+          isPopup: true,
+          customStartTime: 1000,
+          customEndTime: null
+        })
+      });
+      expect(view.addTimeProperties(['m1'])).to.be.eql([
+        "m1[10,10,15]"
+      ]);
+    });
+
+    it("timeRange=0, customStartTime=1000, customEndTime=10000", function() {
+      view.reopen({
+        timeRange: 0,
+        exportTargetView: Em.Object.create({
+          isPopup: true,
+          customStartTime: 1000,
+          customEndTime: 10000
+        })
+      });
+      expect(view.addTimeProperties(['m1'])).to.be.eql([
+        "m1[1,10,15]"
+      ]);
+    });
+  });
+
+  describe("#graphView", function () {
+    var graphView;
+
+    beforeEach(function () {
+      graphView = view.get('graphView').create({
+        parentView: view,
+        _refreshGraph: Em.K,
+        $: function() {
+          return {
+            closest: function() {
+              return {on: Em.K}
+            }
+          }
+        }
+      });
+    });
+
+    describe("#setYAxisFormatter()", function () {
+
+      beforeEach(function () {
+        sinon.stub(App.ChartLinearTimeView, 'DisplayUnitFormatter');
+        graphView.set('yAxisFormatter', null);
+      });
+
+      afterEach(function () {
+        App.ChartLinearTimeView.DisplayUnitFormatter.restore();
+      });
+
+      it("yAxisFormatter should not be set", function () {
+        graphView.reopen({
+          displayUnit: null
+        });
+        graphView.setYAxisFormatter();
+        expect(graphView.get('yAxisFormatter')).to.be.null;
+      });
+
+      it("yAxisFormatter should be set", function () {
+        graphView.reopen({
+          displayUnit: 'u1'
+        });
+        graphView.setYAxisFormatter();
+        expect(graphView.get('yAxisFormatter')).to.be.function;
+      });
+    });
+
+    describe("#setTimeRange", function () {
+
+      beforeEach(function() {
+        sinon.stub(graphView.get('parentView'), 'propertyDidChange');
+      });
+
+      afterEach(function() {
+        graphView.get('parentView').propertyDidChange.restore();
+      });
+
+      it("isPopup=false", function() {
+        graphView.set('isPopup', false);
+        graphView.setTimeRange();
+        expect(graphView.get('parentView.customTimeRange')).to.be.null;
+      });
+
+      it("isPopup=true, currentTimeIndex=8", function() {
+        graphView.set('isPopup', true);
+        graphView.set('currentTimeIndex', 8);
+        graphView.setTimeRange();
+        expect(graphView.get('parentView').propertyDidChange.calledWith('customTimeRange')).to.be.true;
+      });
+
+      it("isPopup=true, currentTimeIndex=1", function() {
+        graphView.set('isPopup', true);
+        graphView.set('currentTimeIndex', 1);
+        graphView.set('timeUnitSeconds', 10);
+        expect(graphView.get('parentView.customTimeRange')).to.be.equal(10);
+      });
+    });
+
+    describe("#id", function () {
+
+      it("should return id", function() {
+        graphView.set('parentView.content.id', 'g1');
+        graphView.propertyDidChange('id');
+        expect(graphView.get('id')).to.be.equal('widget_g1_graph');
+      });
+    });
+
+    describe("#renderer", function () {
+
+      it("should return area", function() {
+        graphView.set('parentView.content.properties.graph_type', 'STACK');
+        graphView.propertyDidChange('renderer');
+        expect(graphView.get('renderer')).to.be.equal('area');
+      });
+
+      it("should return line", function() {
+        graphView.set('parentView.content.properties.graph_type', '');
+        graphView.propertyDidChange('renderer');
+        expect(graphView.get('renderer')).to.be.equal('line');
+      });
+    });
+
+    describe("#transformToSeries()", function () {
+
+      beforeEach(function() {
+        sinon.stub(graphView, 'transformData').returns({});
+      });
+
+      afterEach(function() {
+        graphView.transformData.restore();
+      });
+
+      it("empty data", function() {
+        expect(graphView.transformToSeries([])).to.be.empty;
+      });
+
+      it("should return series", function() {
+        expect(graphView.transformToSeries([{}])).to.be.eql([{}]);
+      });
+    });
+
+    describe("#loadData()", function () {
+
+      beforeEach(function() {
+        sinon.stub(Em.run, 'next', function(context, callback) {
+          callback.apply(context);
+        });
+        sinon.stub(graphView, '_refreshGraph');
+      });
+
+      afterEach(function() {
+        Em.run.next.restore();
+        graphView._refreshGraph.restore();
+      });
+
+      it("_refreshGraph should be called", function() {
+        graphView.loadData();
+        expect(graphView._refreshGraph.calledOnce).to.be.true;
+      });
+    });
+
+    describe("#didInsertElement()", function () {
+
+      beforeEach(function() {
+        sinon.stub(graphView, 'setYAxisFormatter');
+        sinon.stub(graphView, 'loadData');
+        sinon.stub(Em.run, 'next', Em.clb);
+        sinon.stub(App, 'tooltip');
+      });
+
+      afterEach(function() {
+        graphView.setYAxisFormatter.restore();
+        graphView.loadData.restore();
+        Em.run.next.restore();
+        App.tooltip.restore();
+      });
+
+      it("setYAxisFormatter should be called", function() {
+        graphView.didInsertElement();
+        expect(graphView.setYAxisFormatter.calledOnce).to.be.true;
+      });
+
+      it("loadData should be called", function() {
+        graphView.didInsertElement();
+        expect(graphView.loadData.calledOnce).to.be.true;
+      });
+
+      it("App.tooltip should be called, isPreview=false", function() {
+        graphView.didInsertElement();
+        expect(App.tooltip.getCall(0).args[1]).to.be.eql({
+          placement: 'left',
+          template: '<div class="tooltip"><div class="tooltip-arrow"></div><div
class="tooltip-inner graph-tooltip"></div></div>'
+        });
+      });
+
+      it("App.tooltip should be called, isPreview=true", function() {
+        graphView.reopen({
+          isPreview: true
+        });
+        graphView.didInsertElement();
+        expect(App.tooltip.getCall(0).args[1]).to.be.equal('disable');
+      });
+    });
+  });
 });
\ No newline at end of file


Mime
View raw message