This is an automated email from the ASF dual-hosted git repository.

atkach pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 98457d1  AMBARI-25140 Cover widget mixin with unit tests
98457d1 is described below

commit 98457d182d11948820cde1d5c1b47b4ee3bb60d7
Author: Andrii Tkach <atk...@apache.org>
AuthorDate: Mon Feb 4 10:09:56 2019 +0200

    AMBARI-25140 Cover widget mixin with unit tests
---
 .../app/mixins/common/widgets/widget_mixin.js      |  60 +--
 ambari-web/test/mixins/common/widget_mixin_test.js | 481 ++++++++++++++++++++-
 2 files changed, 498 insertions(+), 43 deletions(-)

diff --git a/ambari-web/app/mixins/common/widgets/widget_mixin.js 
b/ambari-web/app/mixins/common/widgets/widget_mixin.js
index 6486856..11ae6bc 100644
--- a/ambari-web/app/mixins/common/widgets/widget_mixin.js
+++ b/ambari-web/app/mixins/common/widgets/widget_mixin.js
@@ -263,7 +263,7 @@ App.WidgetMixin = Ember.Mixin.create({
     };
 
     if (request.tag) {
-      data.selectedHostsParam = '&HostRoles/host_name.in(' + 
App.HDFSService.find().objectAt(0).get('masterComponentGroups').findProperty('name',
 request.tag).hosts.join(',') + ')';
+      data.selectedHostsParam = '&HostRoles/host_name.in(' + 
App.HDFSService.find('HDFS').get('masterComponentGroups').findProperty('name', 
request.tag).hosts.join(',') + ')';
     }
 
     if (metricPaths.length) {
@@ -293,30 +293,15 @@ App.WidgetMixin = Ember.Mixin.create({
    * @param data
    */
   getMetricsSuccessCallback: function (data) {
-    var metrics = [];
     var atLeastOneMetricPresent = false;
 
     if (this.get('content.metrics')) {
       this.get('content.metrics').forEach(function (_metric) {
-        var metric_path = _metric.metric_path;
-        var isAggregatorFunc = false;
-        var metric_data = Em.get(data, metric_path.replace(/\//g, '.'));
+        var metricPath = _metric.metric_path;
+        
+        var metric_data = Em.get(data, metricPath.replace(/\//g, '.'));
         if (Em.isNone(metric_data)) {
-          this.aggregatorFunc.forEach(function (_item) {
-            if (metric_path.endsWith(_item) && !isAggregatorFunc) {
-              isAggregatorFunc = true;
-              var metricBeanProperty = metric_path.split("/").pop();
-              var metricBean;
-              metric_path = metric_path.substring(0, 
metric_path.indexOf(metricBeanProperty));
-              if (metric_path.endsWith("/")) {
-                metric_path = metric_path.slice(0, -1);
-              }
-              metricBean = Em.get(data, metric_path.replace(/\//g, '.'));
-              if (!Em.isNone(metricBean)) {
-                metric_data = metricBean[metricBeanProperty];
-              }
-            }
-          }, this);
+          metric_data = this.parseMetricsWithAggregatorFunc(data, metricPath);
         }
         if (!Em.isNone(metric_data)) {
           atLeastOneMetricPresent = true;
@@ -330,6 +315,28 @@ App.WidgetMixin = Ember.Mixin.create({
       }
     }
   },
+  
+  parseMetricsWithAggregatorFunc: function(data, metric_path) {
+    let isAggregatorFunc = false;
+    let metric = null;
+    this.aggregatorFunc.forEach(function (_item) {
+      if (metric_path.endsWith(_item) && !isAggregatorFunc) {
+        isAggregatorFunc = true;
+        var metricBeanProperty = metric_path.split("/").pop();
+        var metricBean;
+        metric_path = metric_path.substring(0, 
metric_path.indexOf(metricBeanProperty));
+        
+        if (metric_path.endsWith("/")) {
+          metric_path = metric_path.slice(0, -1);
+        }
+        metricBean = Em.get(data, metric_path.replace(/\//g, '.'));
+        if (!Em.isNone(metricBean)) {
+          metric = metricBean[metricBeanProperty];
+        }
+      }
+    }, this);
+    return metric;
+  },
 
   /**
    * if no metrics were received from server then disable graph
@@ -377,8 +384,8 @@ App.WidgetMixin = Ember.Mixin.create({
    * @return {$.ajax}
    */
   getHostComponentsMetrics: function (request) {
-    request.metric_paths.forEach(function (_metric, index) {
-      request.metric_paths[index] = "host_components/" + _metric.metric_path;
+    request.metric_paths  = request.metric_paths.map((_metric) => {
+      return "host_components/" + _metric.metric_path;
     });
     return App.ajax.send({
       name: 'widgets.serviceComponent.metrics.get',
@@ -422,7 +429,7 @@ App.WidgetMixin = Ember.Mixin.create({
   getHostsMetricsSuccessCallback: function (data) {
     var metrics = this.get('content.metrics');
     data.items.forEach(function (item) {
-      metrics.forEach(function (_metric, index) {
+      metrics.forEach(function (_metric) {
         const metric = $.extend({}, _metric, true);
         metric.hostName = item.Hosts.host_name;
         if (!Em.isNone(Em.get(item, _metric.metric_path.replace(/\//g, '.')))) 
{
@@ -574,7 +581,7 @@ App.WidgetMixin = Ember.Mixin.create({
   /*
    * make call when clicking on "clone icon" on widget
    */
-  cloneWidget: function (event) {
+  cloneWidget: function () {
     var self = this;
     return App.showConfirmationPopup(
       function () {
@@ -666,8 +673,7 @@ App.WidgetMixin = Ember.Mixin.create({
     var mainServiceInfoMetricsController =  
App.router.get('mainServiceInfoMetricsController');
     mainServiceInfoMetricsController.saveWidgetLayout(widgets).done(function() 
{
       mainServiceInfoMetricsController.getActiveWidgetLayout().done(function() 
{
-        var newWidget = App.Widget.find().findProperty('id', id);
-        controller.editWidget(newWidget);
+        controller.editWidget(App.Widget.find(id));
       });
     });
   },
@@ -675,7 +681,7 @@ App.WidgetMixin = Ember.Mixin.create({
   /*
    * make call when clicking on "edit icon" on widget
    */
-  editWidget: function (event) {
+  editWidget: function () {
     var self = this;
     var isShared = this.get('content.scope') === 'CLUSTER';
     if (!isShared) {
diff --git a/ambari-web/test/mixins/common/widget_mixin_test.js 
b/ambari-web/test/mixins/common/widget_mixin_test.js
index fb8c5d0..a075100 100644
--- a/ambari-web/test/mixins/common/widget_mixin_test.js
+++ b/ambari-web/test/mixins/common/widget_mixin_test.js
@@ -24,7 +24,13 @@ describe('App.WidgetMixin', function () {
   var mixinObject;
 
   beforeEach(function () {
-    mixinObject = mixinClass.create();
+    mixinObject = mixinClass.create({
+      content: Em.Object.create(),
+      controller: Em.Object.create({
+        hideWidget: sinon.spy(),
+        editWidget: sinon.spy()
+      })
+    });
   });
 
   afterEach(function () {
@@ -81,10 +87,20 @@ describe('App.WidgetMixin', function () {
     beforeEach(function () {
       this.mock = sinon.stub(mixinObject, 'getRequestData');
       sinon.stub(App.WidgetLoadAggregator, 'add');
+      sinon.stub(mixinObject, 'getHostsMetrics').returns({
+        complete: Em.clb
+      });
+      sinon.stub(mixinObject, 'getHostComponentsMetrics').returns({
+        complete: Em.clb
+      });
+      sinon.stub(mixinObject, 'onMetricsLoaded');
     });
     afterEach(function () {
       this.mock.restore();
       App.WidgetLoadAggregator.add.restore();
+      mixinObject.getHostsMetrics.restore();
+      mixinObject.getHostComponentsMetrics.restore();
+      mixinObject.onMetricsLoaded.restore();
     });
     it('has host_component_criteria', function () {
       this.mock.returns({'key1': {host_component_criteria: 'criteria'}});
@@ -100,6 +116,30 @@ describe('App.WidgetMixin', function () {
 
       expect(App.WidgetLoadAggregator.add.calledOnce).to.be.true;
     });
+  
+    it('getHostsMetrics should be called', function () {
+      this.mock.returns({'key1': {
+          host_component_criteria: 'criteria',
+          service_name: 'STACK'
+        }});
+      mixinObject.set('content.widgetType', 'HEATMAP');
+      mixinObject.loadMetrics();
+    
+      expect(mixinObject.getHostsMetrics.calledOnce).to.be.true;
+      expect(mixinObject.onMetricsLoaded.calledOnce).to.be.true;
+    });
+  
+    it('getHostComponentsMetrics should be called', function () {
+      this.mock.returns({'key1': {
+          host_component_criteria: 'criteria',
+          service_name: 'S1'
+        }});
+      mixinObject.set('content.widgetType', 'HEATMAP');
+      mixinObject.loadMetrics();
+    
+      expect(mixinObject.getHostComponentsMetrics.calledOnce).to.be.true;
+      expect(mixinObject.onMetricsLoaded.calledOnce).to.be.true;
+    });
   });
 
   describe("#extractExpressions()", function () {
@@ -264,10 +304,37 @@ describe('App.WidgetMixin', function () {
       });
     });
   });
+  
+  describe('#getHostComponentMetricsSuccessCallback', function() {
+    beforeEach(function() {
+      sinon.stub(mixinObject, 'getMetricsSuccessCallback');
+    });
+    afterEach(function() {
+      mixinObject.getMetricsSuccessCallback.restore();
+    });
+    
+    it('getMetricsSuccessCallback should be called', function() {
+      mixinObject.getHostComponentMetricsSuccessCallback({items: [{}]});
+      expect(mixinObject.getMetricsSuccessCallback.calledWith({})).to.be.true;
+    });
+  });
 
   describe("#getMetricsSuccessCallback()", function () {
+  
+    beforeEach(function() {
+      sinon.stub(mixinObject, 'parseMetricsWithAggregatorFunc').returns(1);
+    });
+    afterEach(function() {
+      mixinObject.parseMetricsWithAggregatorFunc.restore();
+    });
+  
     it("metric is mapped from provided path", function () {
-      var data = {
+      mixinObject.set('content.metrics', [
+        {
+          metric_path: 'metrics/hbase/ipc/IPC/numOpenConnections'
+        }
+      ]);
+      mixinObject.getMetricsSuccessCallback({
         metrics: {
           "hbase": {
             "ipc": {
@@ -277,14 +344,25 @@ describe('App.WidgetMixin', function () {
             }
           }
         }
-      };
+      });
+      expect(mixinObject.get('metrics').findProperty('metric_path', 
'metrics/hbase/ipc/IPC/numOpenConnections').data).to.equal(11.5);
+    });
+  
+    it("parseMetricsWithAggregatorFunc should be called", function () {
       mixinObject.set('content.metrics', [
         {
           metric_path: 'metrics/hbase/ipc/IPC/numOpenConnections'
         }
       ]);
-      mixinObject.getMetricsSuccessCallback(data);
-      expect(mixinObject.get('metrics').findProperty('metric_path', 
'metrics/hbase/ipc/IPC/numOpenConnections').data).to.equal(11.5);
+      mixinObject.getMetricsSuccessCallback({});
+      expect(mixinObject.parseMetricsWithAggregatorFunc.calledWith({}, 
'metrics/hbase/ipc/IPC/numOpenConnections')).to.be.true;
+    });
+  });
+  
+  describe('#parseMetricsWithAggregatorFunc', function() {
+    
+    it('should return metric value', function() {
+      expect(mixinObject.parseMetricsWithAggregatorFunc({path: {foo: {'._sum': 
1}}}, 'path/foo/._sum')).to.equal(1);
     });
   });
 
@@ -377,10 +455,19 @@ describe('App.WidgetMixin', function () {
 
   describe("#getHostComponentMetrics()", function () {
     beforeEach(function () {
-      sinon.stub(mixinObject, 
'computeHostComponentCriteria').returns('criteria')
+      sinon.stub(mixinObject, 
'computeHostComponentCriteria').returns('criteria');
+      sinon.stub(App.HDFSService, 'find').returns(Em.Object.create({
+        masterComponentGroups: [
+          {
+            name: 'tag1',
+            hosts: ['host1', 'host2']
+          }
+        ]
+      }));
     });
     afterEach(function () {
       mixinObject.computeHostComponentCriteria.restore();
+      App.HDFSService.find.restore();
     });
     it("valid request is sent", function () {
       var request = {
@@ -399,7 +486,8 @@ describe('App.WidgetMixin', function () {
             "context": {}
           }
         ],
-        host_component_criteria: 'c1'
+        host_component_criteria: 'c1',
+        tag: 'tag1'
       };
       mixinObject.getHostComponentMetrics(request);
       var args = testHelpers.findAjaxRequest('name', 
'widgets.hostComponent.metrics.get');
@@ -408,7 +496,8 @@ describe('App.WidgetMixin', function () {
       expect(args[0].data).to.be.eql({
         componentName: 'C1',
         metricPaths: 'w1,w2',
-        hostComponentCriteria: 'criteria'
+        hostComponentCriteria: 'criteria',
+        selectedHostsParam: '&HostRoles/host_name.in(host1,host2)'
       });
     });
   });
@@ -501,20 +590,74 @@ describe('App.WidgetMixin', function () {
 
   describe("#postWidgetDefinition()", function () {
     beforeEach(function () {
-      sinon.stub(mixinObject, 'collectWidgetData').returns({});
+      sinon.stub(mixinObject, 'collectWidgetData').returns({
+        WidgetInfo: {
+          widget_name: 'widget1'
+        }
+      });
     });
     afterEach(function () {
       mixinObject.collectWidgetData.restore();
     });
-    it("valid request is sent", function () {
-      mixinObject.postWidgetDefinition();
-      var args = testHelpers.findAjaxRequest('name', 'widgets.wizard.add');
-      expect(args[0]).exists;
-      expect(args[0].sender).to.be.eql(mixinObject);
-      expect(args[0].data).to.be.eql({
-        data: {}
+    it("Request for clone widget should be sent", function () {
+      mixinObject.postWidgetDefinition(true, true);
+      expect(testHelpers.findAjaxRequest('name', 
'widgets.wizard.add')[0]).to.be.eql({
+        name: 'widgets.wizard.add',
+        sender: mixinObject,
+        data: {
+          data: {
+            WidgetInfo: {
+              widget_name: 'widget1(Copy)',
+              scope: 'USER'
+            }
+          }
+        },
+        success: 'editNewClonedWidget'
       });
     });
+  
+    it("Request for new widget should be sent", function () {
+      mixinObject.postWidgetDefinition(false, false);
+      expect(testHelpers.findAjaxRequest('name', 
'widgets.wizard.add')[0]).to.be.eql({
+        name: 'widgets.wizard.add',
+        sender: mixinObject,
+        data: {
+          data: {
+            WidgetInfo: {
+              widget_name: 'widget1'
+            }
+          }
+        },
+        success: 'postWidgetDefinitionSuccessCallback'
+      });
+    });
+  });
+  
+  describe('#postWidgetDefinitionSuccessCallback', function() {
+    var mock = {
+      saveWidgetLayout: sinon.stub().returns({done: Em.clb}),
+      updateActiveLayout: sinon.spy()
+    };
+    beforeEach(function() {
+      sinon.stub(App.router, 'get').returns(mock);
+      mixinObject.set('content.layout', {widgets: []});
+      mixinObject.postWidgetDefinitionSuccessCallback({resources: 
[{WidgetInfo: {id: 1}}]});
+    });
+    afterEach(function() {
+      App.router.get.restore();
+    });
+    
+    it('saveWidgetLayout should be called', function() {
+      expect(mock.saveWidgetLayout.calledWith([
+        Em.Object.create({
+          id: 1
+        })
+      ])).to.be.true;
+    });
+  
+    it('updateActiveLayout should be called', function() {
+      expect(mock.updateActiveLayout.called).to.be.true;
+    });
   });
 
   describe('#getMetricsErrorCallback()', function () {
@@ -674,6 +817,312 @@ describe('App.WidgetMixin', function () {
     });
 
   });
+  
+  describe('#beforeRender', function() {
+    beforeEach(function() {
+      sinon.stub(mixinObject, 'loadMetrics');
+    });
+    afterEach(function() {
+      mixinObject.loadMetrics.restore();
+    });
+    
+    it('loadMetrics should be called', function() {
+      mixinObject.beforeRender();
+      expect(mixinObject.loadMetrics.calledOnce).to.be.true
+;    });
+  });
+  
+  describe('#computeHostComponentCriteria', function() {
+
+    it('should return params', function() {
+      var request = {
+        host_component_criteria: 'host_components/param'
+      };
+      
expect(mixinObject.computeHostComponentCriteria(request)).to.be.equal('&param');
+    });
+  });
+  
+  describe('#getHostComponentsMetrics', function() {
+   
+    it('App.ajax.send should be called', function() {
+      mixinObject.getHostComponentsMetrics({
+        service_name: 'S1',
+        component_name: 'C1',
+        metric_paths: [{metric_path: 'key1'}, {metric_path: 'key2'}]
+      });
+      expect(testHelpers.findAjaxRequest('name', 
'widgets.serviceComponent.metrics.get')[0].data).to.be.eql({
+        serviceName: 'S1',
+        componentName: 'C1',
+        metricPaths: 'host_components/key1,host_components/key2'
+      })
+    });
+  });
+  
+  describe('#getHostComponentsMetricsSuccessCallback', function() {
+    
+    it('should set metrics', function() {
+      var data = {
+        host_components: [
+          {
+            HostRoles: {
+              host_name: 'host1'
+            },
+            path: {
+              foo: 1
+            }
+          }
+        ]
+      };
+      mixinObject.set('content.metrics', [
+        {
+          metric_path: 'path/foo'
+        }
+      ]);
+      mixinObject.set('metrics', []);
+      mixinObject.getHostComponentsMetricsSuccessCallback(data);
+      
expect(JSON.stringify(mixinObject.get('metrics'))).to.be.eql(JSON.stringify([
+        {
+          metric_path: 'path/foo',
+          hostName: 'host1',
+          data: 1
+        }
+      ]));
+    });
+  });
+  
+  describe('#getHostsMetrics', function() {
+    
+    it('App.ajax.send should be called', function() {
+      mixinObject.getHostsMetrics({
+        metric_paths: [{metric_path: 'key1'}, {metric_path: 'key2'}]
+      });
+      expect(testHelpers.findAjaxRequest('name', 
'widgets.hosts.metrics.get')[0].data).to.be.eql({
+        metricPaths: 'key1,key2'
+      })
+    });
+  });
+  
+  describe('#getHostComponentsMetricsSuccessCallback', function() {
+    
+    it('should set metrics', function() {
+      var data = {
+        items: [
+          {
+            Hosts: {
+              host_name: 'host1'
+            },
+            path: {
+              foo: 1
+            }
+          }
+        ]
+      };
+      mixinObject.set('content.metrics', [
+        {
+          metric_path: 'path/foo'
+        }
+      ]);
+      mixinObject.set('metrics', []);
+      mixinObject.getHostsMetricsSuccessCallback(data);
+      
expect(JSON.stringify(mixinObject.get('metrics'))).to.be.eql(JSON.stringify([
+        {
+          metric_path: 'path/foo',
+          hostName: 'host1',
+          data: 1
+        }
+      ]));
+    });
+  });
+  
+  
+  describe('#onMetricsLoaded', function() {
+    beforeEach(function() {
+      sinon.stub(mixinObject, 'drawWidget');
+    });
+    afterEach(function() {
+      mixinObject.drawWidget.restore();
+    });
+    
+    it('drwaWidget should be called', function() {
+      mixinObject.onMetricsLoaded();
+      expect(mixinObject.drawWidget.calledOnce).to.be.true;
+    });
+  
+    it('isLoaded should be true', function() {
+      mixinObject.onMetricsLoaded();
+      expect(mixinObject.get('isLoaded')).to.be.true;
+    });
+  });
+  
+  describe('#drawWidget', function() {
+    beforeEach(function() {
+      sinon.stub(mixinObject, 'calculateValues');
+      mixinObject.set('isLoaded', true);
+      mixinObject.set('content.values', [{computedValue: 1}]);
+      mixinObject.drawWidget();
+    });
+    afterEach(function() {
+      mixinObject.calculateValues.restore();
+    });
+    
+    it('calculateValues should be called', function() {
+      expect(mixinObject.calculateValues.calledOnce).to.be.true;
+    });
+  
+    it('value should be set', function() {
+      expect(mixinObject.get('value')).to.equal(1);
+    });
+  });
+  
+  describe('#hideWidget', function() {
+    
+    it('hideWidget should be called', function() {
+      mixinObject.hideWidget({contexts: [1, 'layout1']});
+      expect(mixinObject.get('controller').hideWidget.calledWith({
+        context: Em.Object.create({
+          id: 1,
+          nsLayout: 'layout1'
+        })
+      })).to.be.true;
+    });
+  });
+  
+  describe('#collectWidgetData', function() {
+    
+    it('should return widget data', function() {
+      mixinObject.set('content', Em.Object.create({
+        widgetName: 'name1',
+        widgetType: 'type1',
+        widgetDescription: 'desc',
+        scope: 'HOST',
+        values: [1],
+        properties: [{}],
+        metrics: [
+          {
+            name: 'metric1',
+            service_name: 'S1',
+            component_name: 'C1',
+            host_component_criteria: 'criteria1',
+            metric_path: 'path/foo',
+            tag: 'tag1'
+          }
+        ]
+      }));
+      expect(mixinObject.collectWidgetData()).to.be.eql({
+        WidgetInfo: {
+          widget_name: 'name1',
+          widget_type: 'type1',
+          description: 'desc',
+          scope: 'HOST',
+          "metrics": [
+            {
+              "name": 'metric1',
+              "service_name": 'S1',
+              "component_name": 'C1',
+              "host_component_criteria":  'criteria1',
+              "metric_path": 'path/foo'
+            }
+          ],
+          values: [1],
+          properties: [{}],
+          tag: 'tag1'
+        }
+      });
+    });
+  });
+  
+  describe('#editNewClonedWidget', function() {
+    var mock = {
+      saveWidgetLayout: sinon.stub().returns({done: Em.clb}),
+      getActiveWidgetLayout: sinon.stub().returns({done: Em.clb})
+    };
+    beforeEach(function() {
+      sinon.stub(App.router, 'get').returns(mock);
+      mixinObject.set('content.layout', {widgets: []});
+      mixinObject.editNewClonedWidget({resources:[{WidgetInfo: {id: 1}}]});
+    });
+    afterEach(function() {
+      App.router.get.restore();
+    });
+    
+    it('saveWidgetLayout should be called', function() {
+      expect(mock.saveWidgetLayout.calledWith([
+        Em.Object.create({
+          id: 1
+        })
+      ])).to.be.true;
+    });
+  
+    it('getActiveWidgetLayout should be called', function() {
+      expect(mock.getActiveWidgetLayout.called).to.be.true;
+    });
+  
+    it('editWidget should be called', function() {
+      expect(mixinObject.get('controller').editWidget.called).to.be.true;
+    });
+  });
+  
+  describe('#editWidget', function() {
+    
+    it('controller.editWidget should be called', function() {
+      mixinObject.set('content', Em.Object.create({
+        scope: 'SERVICE'
+      }));
+      mixinObject.editWidget();
+      
expect(mixinObject.get('controller').editWidget.calledWith(Em.Object.create({
+        scope: 'SERVICE'
+      }))).to.be.true;
+    });
+  
+    it('App.ModalPopup.show should be called', function() {
+      mixinObject.set('content', Em.Object.create({
+        scope: 'CLUSTER'
+      }));
+      mixinObject.editWidget();
+      expect(App.ModalPopup.show.called).to.be.true;
+    });
+  });
+});
+
+describe('App.WidgetPreviewMixin', function() {
+  var widgetPreview;
+  
+  beforeEach(function() {
+    widgetPreview = Em.Object.create({
+      drawWidget: sinon.spy(),
+      loadMetrics: Em.K,
+      controller: Em.Object.create(),
+      content: Em.Object.create()
+    }, App.WidgetPreviewMixin);
+  });
+  
+  describe('#loadMetrics', function() {
+   
+    it('widget properties should be set', function() {
+      widgetPreview.get('controller').setProperties({
+        widgetValues: [1],
+        widgetProperties: [{}],
+        widgetName: 'widget1',
+        widgetMetrics: [{}]
+      });
+      widgetPreview.loadMetrics();
+      expect(widgetPreview.get('content')).to.be.eql(Em.Object.create({
+        'id': 1,
+        'values': [1],
+        'properties': [{}],
+        'widgetName': 'widget1',
+        'metrics': [{}]
+      }));
+    });
+  });
+  
+  describe('#onMetricsLoaded', function() {
+    
+    it('drawWidget should be called', function() {
+      widgetPreview.onMetricsLoaded();
+      expect(widgetPreview.drawWidget.calledOnce).to.be.true;
+    });
+  });
 });
 
 

Reply via email to