text: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  var App = require('app');
  require('views/common/widget/graph_widget_view');
  var fileUtils = require('utils/file_utils');
  
  describe('App.GraphWidgetView', function () {
  
    var view;
  
    beforeEach(function () {
      view = App.GraphWidgetView.create({
        content: Em.Object.create({
          properties: {}
        }),
        parentView: Em.Object.create()
      });
    });
  
    afterEach(function () {
      clearTimeout(view.get('timeoutId'));
      view.destroy();
    });
  
    describe("#adjustData()", function() {
      var testCases = [
        {
          title: 'empty data',
          data: {
            dataLinks: {},
            dataLength: 0
          },
          result: {}
        },
        {
          title: 'correct data',
          data: {
            dataLinks: {
              s1: [[0, 0]]
            },
            dataLength: 1
          },
          result:  {
            s1: [[0, 0]]
          }
        },
        {
          title: 'second series empty',
          data: {
            dataLinks: {
              s1: [[1, 0]],
              s2: []
            },
            dataLength: 1
          },
          result:  {
            s1: [[1, 0]],
            s2: [[null, 0]]
          }
        },
        {
          title: 'second series missing data at the end',
          data: {
            dataLinks: {
              s1: [[1, 0], [2, 1], [3, 2]],
              s2: [[1, 0]]
            },
            dataLength: 3
          },
          result:  {
            s1: [[1, 0], [2, 1], [3, 2]],
            s2: [[1, 0], [null, 1], [null, 2]]
          }
        },
        {
          title: 'second series missing data at the beginning',
          data: {
            dataLinks: {
              s1: [[1, 0], [2, 1], [3, 2]],
              s2: [[3, 2]]
            },
            dataLength: 3
          },
          result:  {
            s1: [[1, 0], [2, 1], [3, 2]],
            s2: [[null, 0], [null, 1], [3, 2]]
          }
        },
        {
          title: 'second series missing data in the middle',
          data: {
            dataLinks: {
              s1: [[1, 0], [2, 1], [3, 2]],
              s2: [[1, 1]]
            },
            dataLength: 3
          },
          result:  {
            s1: [[1, 0], [2, 1], [3, 2]],
            s2: [[null, 0], [1, 1], [null, 2]]
          }
        },
        {
          title: 'second and third series missing data',
          data: {
            dataLinks: {
              s1: [[1, 0], [2, 1], [3, 2]],
              s2: [[1, 1]],
              s3: [[1, 2]]
            },
            dataLength: 3
          },
          result:  {
            s1: [[1, 0], [2, 1], [3, 2]],
            s2: [[null, 0], [1, 1], [null, 2]],
            s3: [[null, 0], [null, 1], [1, 2]]
          }
        }
      ];
  
      testCases.forEach(function (test) {
        it(test.title, function () {
          view.adjustData(test.data.dataLinks, test.data.dataLength);
          expect(test.data.dataLinks).to.eql(test.result);
        });
      });
    });
  
    describe('#exportGraphData', function () {
  
      var cases = [
        {
          data: null,
          downloadTextFileCallCount: 0,
          showAlertPopupCallCount: 1,
          title: 'no data'
        },
        {
          data: {},
          downloadTextFileCallCount: 0,
          showAlertPopupCallCount: 1,
          title: 'invalid data'
        },
        {
          data: [
            {
              data: null
            }
          ],
          downloadTextFileCallCount: 0,
          showAlertPopupCallCount: 1,
          title: 'empty data'
        },
        {
          data: [
            {
              data: {}
            }
          ],
          downloadTextFileCallCount: 0,
          showAlertPopupCallCount: 1,
          title: 'malformed data'
        },
        {
          data: [
            {
              name: 'name',
              data: [0,1]
            }
          ],
          downloadTextFileCallCount: 1,
          showAlertPopupCallCount: 0,
          fileData: '[{"name":"name","data":[0,1]}]',
          title: 'JSON export'
        },
        {
          data: [
            {
              data: [
                {
                  key: 'value'
                }
              ]
            }
          ],
          event: {
            context: true
          },
          downloadTextFileCallCount: 1,
          showAlertPopupCallCount: 0,
          fileData: 'key,value',
          title: 'CSV export'
        }
      ];
  
      cases.forEach(function (item) {
  
        describe(item.title, function () {
  
          beforeEach(function () {
            sinon.stub(view, 'prepareCSV').returns('key,value');
            sinon.stub(fileUtils, 'downloadTextFile', Em.K);
            sinon.stub(App, 'showAlertPopup', Em.K);
            view.set('data', item.data);
            view.exportGraphData(item.event || {});
          });
  
          afterEach(function () {
            view.prepareCSV.restore();
            fileUtils.downloadTextFile.restore();
            App.showAlertPopup.restore();
          });
  
          it('isExportMenuHidden is true', function () {
            expect(view.get('isExportMenuHidden')).to.be.true;
          });
  
          it('downloadTextFile calls count is calid', function () {
            expect(fileUtils.downloadTextFile.callCount).to.equal(item.downloadTextFileCallCount);
          });
  
          it('showAlertPopup calls count is valid', function () {
            expect(App.showAlertPopup.callCount).to.equal(item.showAlertPopupCallCount);
          });
  
          if (item.downloadTextFileCallCount) {
            it('download args are valid', function () {
              var fileType = item.event && item.event.context ? 'csv' : 'json',
                downloadArgs = fileUtils.downloadTextFile.firstCall.args;
              expect(downloadArgs[0].replace(/\s/g, '')).to.equal(item.fileData);
              expect(downloadArgs[1]).to.equal(fileType);
              expect(downloadArgs[2]).to.equal('data.' + fileType);
            });
          }
  
        });
  
      });
  
    });
  
    describe('#exportTargetView', function () {
  
      var childViews = [
          {
            p0: 'v0'
          },
          {
            p1: 'v1'
          }
        ],
        title = 'should take last child view';
  
      beforeEach(function () {
        view.get('childViews').pushObjects(childViews);
        view.propertyDidChange('exportTargetView');
      });
  
      it(title, function () {
        expect(view.get('exportTargetView')).to.eql(childViews[1]);
      });
    });
  
    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', Em.clb);
          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;
        });
      });
  
      // todo: fix test
  
      //describe("#didInsertElement()", function () {
      //
      //  beforeEach(function() {
      //    sinon.stub(graphView, 'loadData');
      //    sinon.stub(Em.run, 'next', Em.clb);
      //    sinon.stub(App, 'tooltip');
      //  });
      //
      //  afterEach(function() {
      //    graphView.loadData.restore();
      //    Em.run.next.restore();
      //    App.tooltip.restore();
      //  });
      //
      //  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');
      //  });
      //});
    });
  });