Ver código fonte

refactor: moved influxdb specs to plugins folder

Torkel Ödegaard 10 anos atrás
pai
commit
7d2646f60a

+ 3 - 3
public/app/plugins/datasource/influxdb/datasource.js

@@ -2,10 +2,10 @@ define([
   'angular',
   'lodash',
   'app/core/utils/datemath',
-  './influxSeries',
-  './queryBuilder',
+  './influx_series',
+  './query_builder',
   './directives',
-  './queryCtrl',
+  './query_ctrl',
 ],
 function (angular, _, dateMath, InfluxSeries, InfluxQueryBuilder) {
   'use strict';

+ 0 - 0
public/app/plugins/datasource/influxdb/influxSeries.js → public/app/plugins/datasource/influxdb/influx_series.js


+ 0 - 0
public/app/plugins/datasource/influxdb/queryBuilder.js → public/app/plugins/datasource/influxdb/query_builder.js


+ 1 - 1
public/app/plugins/datasource/influxdb/queryCtrl.js → public/app/plugins/datasource/influxdb/query_ctrl.js

@@ -1,7 +1,7 @@
 define([
   'angular',
   'lodash',
-  './queryBuilder',
+  './query_builder',
 ],
 function (angular, _, InfluxQueryBuilder) {
   'use strict';

+ 190 - 0
public/app/plugins/datasource/influxdb/specs/influx_series_specs.ts

@@ -0,0 +1,190 @@
+///<amd-dependency path="app/plugins/datasource/influxdb/influx_series" name="InfluxSeries"/>
+
+import {describe, beforeEach, it, sinon, expect} from 'test/lib/common';
+
+declare var InfluxSeries: any;
+
+describe('when generating timeseries from influxdb response', function() {
+
+  describe('given multiple fields for series', function() {
+    var options = {
+      alias: '',
+      series: [
+        {
+          name: 'cpu',
+          tags:  {app: 'test', server: 'server1'},
+          columns: ['time', 'mean', 'max', 'min'],
+          values: [[1431946625000, 10, 11, 9], [1431946626000, 20, 21, 19]]
+        }
+      ]
+    };
+    describe('and no alias', function() {
+      it('should generate multiple datapoints for each column', function() {
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result.length).to.be(3);
+        expect(result[0].target).to.be('cpu.mean {app: test, server: server1}');
+        expect(result[0].datapoints[0][0]).to.be(10);
+        expect(result[0].datapoints[0][1]).to.be(1431946625000);
+        expect(result[0].datapoints[1][0]).to.be(20);
+        expect(result[0].datapoints[1][1]).to.be(1431946626000);
+
+        expect(result[1].target).to.be('cpu.max {app: test, server: server1}');
+        expect(result[1].datapoints[0][0]).to.be(11);
+        expect(result[1].datapoints[0][1]).to.be(1431946625000);
+        expect(result[1].datapoints[1][0]).to.be(21);
+        expect(result[1].datapoints[1][1]).to.be(1431946626000);
+
+        expect(result[2].target).to.be('cpu.min {app: test, server: server1}');
+        expect(result[2].datapoints[0][0]).to.be(9);
+        expect(result[2].datapoints[0][1]).to.be(1431946625000);
+        expect(result[2].datapoints[1][0]).to.be(19);
+        expect(result[2].datapoints[1][1]).to.be(1431946626000);
+
+      });
+    });
+
+    describe('and simple alias', function() {
+      it('should use alias', function() {
+        options.alias = 'new series';
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result[0].target).to.be('new series');
+        expect(result[1].target).to.be('new series');
+        expect(result[2].target).to.be('new series');
+      });
+
+    });
+
+    describe('and alias patterns', function() {
+      it('should replace patterns', function() {
+        options.alias = 'alias: $m -> $tag_server ([[measurement]])';
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result[0].target).to.be('alias: cpu -> server1 (cpu)');
+        expect(result[1].target).to.be('alias: cpu -> server1 (cpu)');
+        expect(result[2].target).to.be('alias: cpu -> server1 (cpu)');
+      });
+
+    });
+  });
+  describe('given measurement with default fieldname', function() {
+    var options = { series: [
+      {
+        name: 'cpu',
+        tags:  {app: 'test', server: 'server1'},
+        columns: ['time', 'value'],
+        values: [["2015-05-18T10:57:05Z", 10], ["2015-05-18T10:57:06Z", 12]]
+      },
+      {
+        name: 'cpu',
+        tags:  {app: 'test2', server: 'server2'},
+        columns: ['time', 'value'],
+        values: [["2015-05-18T10:57:05Z", 15], ["2015-05-18T10:57:06Z", 16]]
+      }
+    ]};
+
+    describe('and no alias', function() {
+
+      it('should generate label with no field', function() {
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result[0].target).to.be('cpu {app: test, server: server1}');
+        expect(result[1].target).to.be('cpu {app: test2, server: server2}');
+      });
+    });
+
+  });
+  describe('given two series', function() {
+    var options = {
+      alias: '',
+      series: [
+        {
+          name: 'cpu',
+          tags:  {app: 'test', server: 'server1'},
+          columns: ['time', 'mean'],
+          values: [[1431946625000, 10], [1431946626000, 12]]
+        },
+        {
+          name: 'cpu',
+          tags:  {app: 'test2', server: 'server2'},
+          columns: ['time', 'mean'],
+          values: [[1431946625000, 15], [1431946626000, 16]]
+        }
+      ]
+    };
+
+    describe('and no alias', function() {
+
+      it('should generate two time series', function() {
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result.length).to.be(2);
+        expect(result[0].target).to.be('cpu.mean {app: test, server: server1}');
+        expect(result[0].datapoints[0][0]).to.be(10);
+        expect(result[0].datapoints[0][1]).to.be(1431946625000);
+        expect(result[0].datapoints[1][0]).to.be(12);
+        expect(result[0].datapoints[1][1]).to.be(1431946626000);
+
+        expect(result[1].target).to.be('cpu.mean {app: test2, server: server2}');
+        expect(result[1].datapoints[0][0]).to.be(15);
+        expect(result[1].datapoints[0][1]).to.be(1431946625000);
+        expect(result[1].datapoints[1][0]).to.be(16);
+        expect(result[1].datapoints[1][1]).to.be(1431946626000);
+      });
+    });
+
+    describe('and simple alias', function() {
+      it('should use alias', function() {
+        options.alias = 'new series';
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result[0].target).to.be('new series');
+      });
+
+    });
+
+    describe('and alias patterns', function() {
+      it('should replace patterns', function() {
+        options.alias = 'alias: $m -> $tag_server ([[measurement]])';
+        var series = new InfluxSeries(options);
+        var result = series.getTimeSeries();
+
+        expect(result[0].target).to.be('alias: cpu -> server1 (cpu)');
+        expect(result[1].target).to.be('alias: cpu -> server2 (cpu)');
+      });
+
+    });
+
+  });
+
+  describe('given measurement with dots', function() {
+    var options = {
+      alias: '',
+      series: [
+        {
+          name: 'app.prod.server1.count',
+          tags:  {},
+          columns: ['time', 'mean'],
+          values: [[1431946625000, 10], [1431946626000, 12]]
+        }
+      ]
+    };
+
+    it('should replace patterns', function() {
+      options.alias = 'alias: $1 -> [[3]]';
+      var series = new InfluxSeries(options);
+      var result = series.getTimeSeries();
+
+      expect(result[0].target).to.be('alias: prod -> count');
+    });
+  });
+
+});
+

+ 186 - 0
public/app/plugins/datasource/influxdb/specs/query_builder_specs.ts

@@ -0,0 +1,186 @@
+///<amd-dependency path="app/plugins/datasource/influxdb/query_builder" name="InfluxQueryBuilder"/>
+//
+import {describe, beforeEach, it, sinon, expect} from 'test/lib/common';
+
+declare var InfluxQueryBuilder: any;
+
+describe('InfluxQueryBuilder', function() {
+
+  describe('series with mesurement only', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      groupBy: [{type: 'time', interval: 'auto'}]
+      });
+
+      var query = builder.build();
+
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with math expr and as expr', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      fields: [{name: 'test', func: 'max', mathExpr: '*2', asExpr: 'new_name'}],
+      groupBy: [{type: 'time', interval: 'auto'}]
+      });
+
+      var query = builder.build();
+
+      expect(query).to.be('SELECT max("test")*2 AS "new_name" FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with single tag only', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      groupBy: [{type: 'time', interval: 'auto'}],
+      tags: [{key: 'hostname', value: 'server1'}]
+      });
+
+      var query = builder.build();
+
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' AND $timeFilter'
+          + ' GROUP BY time($interval)');
+    });
+
+    it('should switch regex operator with tag value is regex', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      groupBy: [{type: 'time', interval: 'auto'}],
+      tags: [{key: 'app', value: '/e.*/'}]
+      });
+
+      var query = builder.build();
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "app" =~ /e.*/ AND $timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with multiple fields', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      tags: [],
+      groupBy: [{type: 'time', interval: 'auto'}],
+      fields: [{ name: 'tx_in', func: 'sum' }, { name: 'tx_out', func: 'mean' }]
+      });
+
+      var query = builder.build();
+      expect(query).to.be('SELECT sum("tx_in") AS "tx_in", mean("tx_out") AS "tx_out" ' +
+          'FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with multiple tags only', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      groupBy: [{type: 'time', interval: 'auto'}],
+      tags: [{key: 'hostname', value: 'server1'}, {key: 'app', value: 'email', condition: "AND"}]
+      });
+
+      var query = builder.build();
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' AND "app" = \'email\' AND ' +
+          '$timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with tags OR condition', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      groupBy: [{type: 'time', interval: 'auto'}],
+      tags: [{key: 'hostname', value: 'server1'}, {key: 'hostname', value: 'server2', condition: "OR"}]
+      });
+
+      var query = builder.build();
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' OR "hostname" = \'server2\' AND ' +
+          '$timeFilter GROUP BY time($interval)');
+    });
+  });
+
+  describe('series with groupByTag', function() {
+    it('should generate correct query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: 'cpu',
+      tags: [],
+      groupBy: [{type: 'time', interval: 'auto'}, {type: 'tag', key: 'host'}],
+      });
+
+      var query = builder.build();
+      expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE $timeFilter ' +
+          'GROUP BY time($interval), "host"');
+    });
+  });
+
+  describe('when building explore queries', function() {
+
+    it('should only have measurement condition in tag keys query given query with measurement', function() {
+      var builder = new InfluxQueryBuilder({ measurement: 'cpu', tags: [] });
+      var query = builder.buildExploreQuery('TAG_KEYS');
+      expect(query).to.be('SHOW TAG KEYS FROM "cpu"');
+    });
+
+    it('should handle regex measurement in tag keys query', function() {
+      var builder = new InfluxQueryBuilder({
+      measurement: '/.*/',
+      tags: []
+      });
+      var query = builder.buildExploreQuery('TAG_KEYS');
+      expect(query).to.be('SHOW TAG KEYS FROM /.*/');
+    });
+
+    it('should have no conditions in tags keys query given query with no measurement or tag', function() {
+      var builder = new InfluxQueryBuilder({ measurement: '', tags: [] });
+      var query = builder.buildExploreQuery('TAG_KEYS');
+      expect(query).to.be('SHOW TAG KEYS');
+    });
+
+    it('should have where condition in tag keys query with tags', function() {
+      var builder = new InfluxQueryBuilder({ measurement: '', tags: [{key: 'host', value: 'se1'}] });
+      var query = builder.buildExploreQuery('TAG_KEYS');
+      expect(query).to.be("SHOW TAG KEYS WHERE \"host\" = 'se1'");
+    });
+
+    it('should have no conditions in measurement query for query with no tags', function() {
+      var builder = new InfluxQueryBuilder({ measurement: '', tags: [] });
+      var query = builder.buildExploreQuery('MEASUREMENTS');
+      expect(query).to.be('SHOW MEASUREMENTS');
+    });
+
+    it('should have where condition in measurement query for query with tags', function() {
+      var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'email'}]});
+      var query = builder.buildExploreQuery('MEASUREMENTS');
+      expect(query).to.be("SHOW MEASUREMENTS WHERE \"app\" = 'email'");
+    });
+
+    it('should have where tag name IN filter in tag values query for query with one tag', function() {
+      var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'asdsadsad'}]});
+      var query = builder.buildExploreQuery('TAG_VALUES', 'app');
+      expect(query).to.be('SHOW TAG VALUES WITH KEY = "app"');
+    });
+
+    it('should have measurement tag condition and tag name IN filter in tag values query', function() {
+      var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}, {key: 'host', value: 'server1'}]});
+      var query = builder.buildExploreQuery('TAG_VALUES', 'app');
+      expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE "host" = \'server1\'');
+    });
+
+    it('should switch to regex operator in tag condition', function() {
+      var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'host', value: '/server.*/'}]});
+      var query = builder.buildExploreQuery('TAG_VALUES', 'app');
+      expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE "host" =~ /server.*/');
+    });
+
+    it('should build show field query', function() {
+      var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}]});
+      var query = builder.buildExploreQuery('FIELDS');
+      expect(query).to.be('SHOW FIELD KEYS FROM "cpu"');
+    });
+
+  });
+
+});

+ 188 - 0
public/app/plugins/datasource/influxdb/specs/query_ctrl_specs.ts

@@ -0,0 +1,188 @@
+///<amd-dependency path="app/plugins/datasource/influxdb/query_ctrl"/>
+///<amd-dependency path="app/services/uiSegmentSrv" />
+///<amd-dependency path="test/specs/helpers" name="helpers" />
+
+import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
+
+declare var helpers: any;
+
+describe('InfluxDBQueryCtrl', function() {
+  var ctx = new helpers.ControllerTestContext();
+
+  beforeEach(angularMocks.module('grafana.controllers'));
+  beforeEach(angularMocks.module('grafana.services'));
+  beforeEach(ctx.providePhase());
+  beforeEach(ctx.createControllerPhase('InfluxQueryCtrl'));
+
+  beforeEach(function() {
+    ctx.scope.target = {};
+    ctx.scope.$parent = { get_data: sinon.spy() };
+
+    ctx.scope.datasource = ctx.datasource;
+    ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
+  });
+
+  describe('init', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+    });
+
+    it('should init tagSegments', function() {
+      expect(ctx.scope.tagSegments.length).to.be(1);
+    });
+
+    it('should init measurementSegment', function() {
+      expect(ctx.scope.measurementSegment.value).to.be('select measurement');
+    });
+  });
+
+  describe('when first tag segment is updated', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
+    });
+
+    it('should update tag key', function() {
+      expect(ctx.scope.target.tags[0].key).to.be('asd');
+      expect(ctx.scope.tagSegments[0].type).to.be('key');
+    });
+
+    it('should add tagSegments', function() {
+      expect(ctx.scope.tagSegments.length).to.be(3);
+    });
+  });
+
+  describe('when last tag value segment is updated', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+    });
+
+    it('should update tag value', function() {
+      expect(ctx.scope.target.tags[0].value).to.be('server1');
+    });
+
+    it('should set tag operator', function() {
+      expect(ctx.scope.target.tags[0].operator).to.be('=');
+    });
+
+    it('should add plus button for another filter', function() {
+      expect(ctx.scope.tagSegments[3].fake).to.be(true);
+    });
+  });
+
+  describe('when last tag value segment is updated to regex', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
+      ctx.scope.tagSegmentUpdated({value: '/server.*/', type: 'value'}, 2);
+    });
+
+    it('should update operator', function() {
+      expect(ctx.scope.tagSegments[1].value).to.be('=~');
+      expect(ctx.scope.target.tags[0].operator).to.be('=~');
+    });
+  });
+
+  describe('when second tag key is added', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
+    });
+
+    it('should update tag key', function() {
+      expect(ctx.scope.target.tags[1].key).to.be('key2');
+    });
+
+    it('should add AND segment', function() {
+      expect(ctx.scope.tagSegments[3].value).to.be('AND');
+    });
+  });
+
+  describe('when condition is changed', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
+      ctx.scope.tagSegmentUpdated({value: 'OR', type: 'condition'}, 3);
+    });
+
+    it('should update tag condition', function() {
+      expect(ctx.scope.target.tags[1].condition).to.be('OR');
+    });
+
+    it('should update AND segment', function() {
+      expect(ctx.scope.tagSegments[3].value).to.be('OR');
+      expect(ctx.scope.tagSegments.length).to.be(7);
+    });
+  });
+
+  describe('when deleting first tag filter after value is selected', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 0);
+    });
+
+    it('should remove tags', function() {
+      expect(ctx.scope.target.tags.length).to.be(0);
+    });
+
+    it('should remove all segment after 2 and replace with plus button', function() {
+      expect(ctx.scope.tagSegments.length).to.be(1);
+      expect(ctx.scope.tagSegments[0].type).to.be('plus-button');
+    });
+  });
+
+  describe('when deleting second tag value before second tag value is complete', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
+      ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
+    });
+
+    it('should remove all segment after 2 and replace with plus button', function() {
+      expect(ctx.scope.tagSegments.length).to.be(4);
+      expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
+    });
+  });
+
+  describe('when deleting second tag value before second tag value is complete', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
+      ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
+    });
+
+    it('should remove all segment after 2 and replace with plus button', function() {
+      expect(ctx.scope.tagSegments.length).to.be(4);
+      expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
+    });
+  });
+
+  describe('when deleting second tag value after second tag filter is complete', function() {
+    beforeEach(function() {
+      ctx.scope.init();
+      ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
+      ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
+      ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
+      ctx.scope.tagSegmentUpdated({value: 'value', type: 'value'}, 6);
+      ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
+    });
+
+    it('should remove all segment after 2 and replace with plus button', function() {
+      expect(ctx.scope.tagSegments.length).to.be(4);
+      expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
+    });
+  });
+
+});

+ 0 - 187
public/test/specs/influx09-querybuilder-specs.js

@@ -1,187 +0,0 @@
-define([
-  'app/plugins/datasource/influxdb/queryBuilder'
-], function(InfluxQueryBuilder) {
-  'use strict';
-
-  describe('InfluxQueryBuilder', function() {
-
-    describe('series with mesurement only', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          groupBy: [{type: 'time', interval: 'auto'}]
-        });
-
-        var query = builder.build();
-
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with math expr and as expr', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          fields: [{name: 'test', func: 'max', mathExpr: '*2', asExpr: 'new_name'}],
-          groupBy: [{type: 'time', interval: 'auto'}]
-        });
-
-        var query = builder.build();
-
-        expect(query).to.be('SELECT max("test")*2 AS "new_name" FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with single tag only', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          groupBy: [{type: 'time', interval: 'auto'}],
-          tags: [{key: 'hostname', value: 'server1'}]
-        });
-
-        var query = builder.build();
-
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' AND $timeFilter'
-                            + ' GROUP BY time($interval)');
-      });
-
-      it('should switch regex operator with tag value is regex', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          groupBy: [{type: 'time', interval: 'auto'}],
-          tags: [{key: 'app', value: '/e.*/'}]
-        });
-
-        var query = builder.build();
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "app" =~ /e.*/ AND $timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with multiple fields', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          tags: [],
-          groupBy: [{type: 'time', interval: 'auto'}],
-          fields: [{ name: 'tx_in', func: 'sum' }, { name: 'tx_out', func: 'mean' }]
-        });
-
-        var query = builder.build();
-        expect(query).to.be('SELECT sum("tx_in") AS "tx_in", mean("tx_out") AS "tx_out" ' +
-                            'FROM "cpu" WHERE $timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with multiple tags only', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          groupBy: [{type: 'time', interval: 'auto'}],
-          tags: [{key: 'hostname', value: 'server1'}, {key: 'app', value: 'email', condition: "AND"}]
-        });
-
-        var query = builder.build();
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' AND "app" = \'email\' AND ' +
-                            '$timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with tags OR condition', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          groupBy: [{type: 'time', interval: 'auto'}],
-          tags: [{key: 'hostname', value: 'server1'}, {key: 'hostname', value: 'server2', condition: "OR"}]
-        });
-
-        var query = builder.build();
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE "hostname" = \'server1\' OR "hostname" = \'server2\' AND ' +
-                            '$timeFilter GROUP BY time($interval)');
-      });
-    });
-
-    describe('series with groupByTag', function() {
-      it('should generate correct query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: 'cpu',
-          tags: [],
-          groupBy: [{type: 'time', interval: 'auto'}, {type: 'tag', key: 'host'}],
-        });
-
-        var query = builder.build();
-        expect(query).to.be('SELECT mean("value") AS "value" FROM "cpu" WHERE $timeFilter ' +
-                            'GROUP BY time($interval), "host"');
-      });
-    });
-
-    describe('when building explore queries', function() {
-
-      it('should only have measurement condition in tag keys query given query with measurement', function() {
-        var builder = new InfluxQueryBuilder({ measurement: 'cpu', tags: [] });
-        var query = builder.buildExploreQuery('TAG_KEYS');
-        expect(query).to.be('SHOW TAG KEYS FROM "cpu"');
-      });
-
-      it('should handle regex measurement in tag keys query', function() {
-        var builder = new InfluxQueryBuilder({
-          measurement: '/.*/',
-          tags: []
-        });
-        var query = builder.buildExploreQuery('TAG_KEYS');
-        expect(query).to.be('SHOW TAG KEYS FROM /.*/');
-      });
-
-      it('should have no conditions in tags keys query given query with no measurement or tag', function() {
-        var builder = new InfluxQueryBuilder({ measurement: '', tags: [] });
-        var query = builder.buildExploreQuery('TAG_KEYS');
-        expect(query).to.be('SHOW TAG KEYS');
-      });
-
-      it('should have where condition in tag keys query with tags', function() {
-        var builder = new InfluxQueryBuilder({ measurement: '', tags: [{key: 'host', value: 'se1'}] });
-        var query = builder.buildExploreQuery('TAG_KEYS');
-        expect(query).to.be("SHOW TAG KEYS WHERE \"host\" = 'se1'");
-      });
-
-      it('should have no conditions in measurement query for query with no tags', function() {
-        var builder = new InfluxQueryBuilder({ measurement: '', tags: [] });
-        var query = builder.buildExploreQuery('MEASUREMENTS');
-        expect(query).to.be('SHOW MEASUREMENTS');
-      });
-
-      it('should have where condition in measurement query for query with tags', function() {
-        var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'email'}]});
-        var query = builder.buildExploreQuery('MEASUREMENTS');
-        expect(query).to.be("SHOW MEASUREMENTS WHERE \"app\" = 'email'");
-      });
-
-      it('should have where tag name IN filter in tag values query for query with one tag', function() {
-        var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'asdsadsad'}]});
-        var query = builder.buildExploreQuery('TAG_VALUES', 'app');
-        expect(query).to.be('SHOW TAG VALUES WITH KEY = "app"');
-      });
-
-      it('should have measurement tag condition and tag name IN filter in tag values query', function() {
-        var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}, {key: 'host', value: 'server1'}]});
-        var query = builder.buildExploreQuery('TAG_VALUES', 'app');
-        expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE "host" = \'server1\'');
-      });
-
-      it('should switch to regex operator in tag condition', function() {
-        var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'host', value: '/server.*/'}]});
-        var query = builder.buildExploreQuery('TAG_VALUES', 'app');
-        expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE "host" =~ /server.*/');
-      });
-
-      it('should build show field query', function() {
-        var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}]});
-        var query = builder.buildExploreQuery('FIELDS');
-        expect(query).to.be('SHOW FIELD KEYS FROM "cpu"');
-      });
-
-    });
-
-  });
-
-});

+ 0 - 180
public/test/specs/influxSeries-specs.js

@@ -1,180 +0,0 @@
-define([
-  'app/plugins/datasource/influxdb/influxSeries'
-], function(InfluxSeries) {
-  'use strict';
-
-  describe('when generating timeseries from influxdb response', function() {
-
-    describe('given multiple fields for series', function() {
-      var options = { series: [
-        {
-          name: 'cpu',
-          tags:  {app: 'test', server: 'server1'},
-          columns: ['time', 'mean', 'max', 'min'],
-          values: [[1431946625000, 10, 11, 9], [1431946626000, 20, 21, 19]]
-        }
-      ]};
-      describe('and no alias', function() {
-        it('should generate multiple datapoints for each column', function() {
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result.length).to.be(3);
-          expect(result[0].target).to.be('cpu.mean {app: test, server: server1}');
-          expect(result[0].datapoints[0][0]).to.be(10);
-          expect(result[0].datapoints[0][1]).to.be(1431946625000);
-          expect(result[0].datapoints[1][0]).to.be(20);
-          expect(result[0].datapoints[1][1]).to.be(1431946626000);
-
-          expect(result[1].target).to.be('cpu.max {app: test, server: server1}');
-          expect(result[1].datapoints[0][0]).to.be(11);
-          expect(result[1].datapoints[0][1]).to.be(1431946625000);
-          expect(result[1].datapoints[1][0]).to.be(21);
-          expect(result[1].datapoints[1][1]).to.be(1431946626000);
-
-          expect(result[2].target).to.be('cpu.min {app: test, server: server1}');
-          expect(result[2].datapoints[0][0]).to.be(9);
-          expect(result[2].datapoints[0][1]).to.be(1431946625000);
-          expect(result[2].datapoints[1][0]).to.be(19);
-          expect(result[2].datapoints[1][1]).to.be(1431946626000);
-
-        });
-      });
-
-      describe('and simple alias', function() {
-        it('should use alias', function() {
-          options.alias = 'new series';
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('new series');
-          expect(result[1].target).to.be('new series');
-          expect(result[2].target).to.be('new series');
-        });
-
-      });
-
-      describe('and alias patterns', function() {
-        it('should replace patterns', function() {
-          options.alias = 'alias: $m -> $tag_server ([[measurement]])';
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('alias: cpu -> server1 (cpu)');
-          expect(result[1].target).to.be('alias: cpu -> server1 (cpu)');
-          expect(result[2].target).to.be('alias: cpu -> server1 (cpu)');
-        });
-
-      });
-    });
-    describe('given measurement with default fieldname', function() {
-      var options = { series: [
-        {
-          name: 'cpu',
-          tags:  {app: 'test', server: 'server1'},
-          columns: ['time', 'value'],
-          values: [["2015-05-18T10:57:05Z", 10], ["2015-05-18T10:57:06Z", 12]]
-        },
-        {
-          name: 'cpu',
-          tags:  {app: 'test2', server: 'server2'},
-          columns: ['time', 'value'],
-          values: [["2015-05-18T10:57:05Z", 15], ["2015-05-18T10:57:06Z", 16]]
-        }
-      ]};
-
-      describe('and no alias', function() {
-
-        it('should generate label with no field', function() {
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('cpu {app: test, server: server1}');
-          expect(result[1].target).to.be('cpu {app: test2, server: server2}');
-        });
-      });
-
-    });
-    describe('given two series', function() {
-      var options = { series: [
-        {
-          name: 'cpu',
-          tags:  {app: 'test', server: 'server1'},
-          columns: ['time', 'mean'],
-          values: [[1431946625000, 10], [1431946626000, 12]]
-        },
-        {
-          name: 'cpu',
-          tags:  {app: 'test2', server: 'server2'},
-          columns: ['time', 'mean'],
-          values: [[1431946625000, 15], [1431946626000, 16]]
-        }
-      ]};
-
-      describe('and no alias', function() {
-
-        it('should generate two time series', function() {
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result.length).to.be(2);
-          expect(result[0].target).to.be('cpu.mean {app: test, server: server1}');
-          expect(result[0].datapoints[0][0]).to.be(10);
-          expect(result[0].datapoints[0][1]).to.be(1431946625000);
-          expect(result[0].datapoints[1][0]).to.be(12);
-          expect(result[0].datapoints[1][1]).to.be(1431946626000);
-
-          expect(result[1].target).to.be('cpu.mean {app: test2, server: server2}');
-          expect(result[1].datapoints[0][0]).to.be(15);
-          expect(result[1].datapoints[0][1]).to.be(1431946625000);
-          expect(result[1].datapoints[1][0]).to.be(16);
-          expect(result[1].datapoints[1][1]).to.be(1431946626000);
-        });
-      });
-
-      describe('and simple alias', function() {
-        it('should use alias', function() {
-          options.alias = 'new series';
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('new series');
-        });
-
-      });
-
-      describe('and alias patterns', function() {
-        it('should replace patterns', function() {
-          options.alias = 'alias: $m -> $tag_server ([[measurement]])';
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('alias: cpu -> server1 (cpu)');
-          expect(result[1].target).to.be('alias: cpu -> server2 (cpu)');
-        });
-
-      });
-
-    });
-
-    describe('given measurement with dots', function() {
-      var options = { series: [
-        {
-          name: 'app.prod.server1.count',
-          tags:  {},
-          columns: ['time', 'mean'],
-          values: [[1431946625000, 10], [1431946626000, 12]]
-        }
-      ]};
-
-      it('should replace patterns', function() {
-          options.alias = 'alias: $1 -> [[3]]';
-          var series = new InfluxSeries(options);
-          var result = series.getTimeSeries();
-
-          expect(result[0].target).to.be('alias: prod -> count');
-      });
-    });
-  });
-
-});

+ 0 - 188
public/test/specs/influxdbQueryCtrl-specs.js

@@ -1,188 +0,0 @@
-define([
-  './helpers',
-  'app/plugins/datasource/influxdb/queryCtrl',
-  'app/services/uiSegmentSrv'
-], function(helpers) {
-  'use strict';
-
-  describe('InfluxDBQueryCtrl', function() {
-    var ctx = new helpers.ControllerTestContext();
-
-    beforeEach(module('grafana.controllers'));
-    beforeEach(module('grafana.services'));
-    beforeEach(ctx.providePhase());
-    beforeEach(ctx.createControllerPhase('InfluxQueryCtrl'));
-
-    beforeEach(function() {
-      ctx.scope.target = {};
-      ctx.scope.$parent = { get_data: sinon.spy() };
-
-      ctx.scope.datasource = ctx.datasource;
-      ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
-    });
-
-    describe('init', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-      });
-
-      it('should init tagSegments', function() {
-        expect(ctx.scope.tagSegments.length).to.be(1);
-      });
-
-      it('should init measurementSegment', function() {
-        expect(ctx.scope.measurementSegment.value).to.be('select measurement');
-      });
-    });
-
-    describe('when first tag segment is updated', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
-      });
-
-      it('should update tag key', function() {
-        expect(ctx.scope.target.tags[0].key).to.be('asd');
-        expect(ctx.scope.tagSegments[0].type).to.be('key');
-      });
-
-      it('should add tagSegments', function() {
-        expect(ctx.scope.tagSegments.length).to.be(3);
-      });
-    });
-
-    describe('when last tag value segment is updated', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-      });
-
-      it('should update tag value', function() {
-        expect(ctx.scope.target.tags[0].value).to.be('server1');
-      });
-
-      it('should set tag operator', function() {
-        expect(ctx.scope.target.tags[0].operator).to.be('=');
-      });
-
-      it('should add plus button for another filter', function() {
-        expect(ctx.scope.tagSegments[3].fake).to.be(true);
-      });
-    });
-
-    describe('when last tag value segment is updated to regex', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button'}, 0);
-        ctx.scope.tagSegmentUpdated({value: '/server.*/', type: 'value'}, 2);
-      });
-
-      it('should update operator', function() {
-        expect(ctx.scope.tagSegments[1].value).to.be('=~');
-        expect(ctx.scope.target.tags[0].operator).to.be('=~');
-      });
-    });
-
-    describe('when second tag key is added', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
-      });
-
-      it('should update tag key', function() {
-        expect(ctx.scope.target.tags[1].key).to.be('key2');
-      });
-
-      it('should add AND segment', function() {
-        expect(ctx.scope.tagSegments[3].value).to.be('AND');
-      });
-    });
-
-    describe('when condition is changed', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
-        ctx.scope.tagSegmentUpdated({value: 'OR', type: 'condition'}, 3);
-      });
-
-      it('should update tag condition', function() {
-        expect(ctx.scope.target.tags[1].condition).to.be('OR');
-      });
-
-      it('should update AND segment', function() {
-        expect(ctx.scope.tagSegments[3].value).to.be('OR');
-        expect(ctx.scope.tagSegments.length).to.be(7);
-      });
-    });
-
-    describe('when deleting first tag filter after value is selected', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 0);
-      });
-
-      it('should remove tags', function() {
-        expect(ctx.scope.target.tags.length).to.be(0);
-      });
-
-      it('should remove all segment after 2 and replace with plus button', function() {
-        expect(ctx.scope.tagSegments.length).to.be(1);
-        expect(ctx.scope.tagSegments[0].type).to.be('plus-button');
-      });
-    });
-
-    describe('when deleting second tag value before second tag value is complete', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
-        ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
-      });
-
-      it('should remove all segment after 2 and replace with plus button', function() {
-        expect(ctx.scope.tagSegments.length).to.be(4);
-        expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
-      });
-    });
-
-    describe('when deleting second tag value before second tag value is complete', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
-        ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
-      });
-
-      it('should remove all segment after 2 and replace with plus button', function() {
-        expect(ctx.scope.tagSegments.length).to.be(4);
-        expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
-      });
-    });
-
-    describe('when deleting second tag value after second tag filter is complete', function() {
-      beforeEach(function() {
-        ctx.scope.init();
-        ctx.scope.tagSegmentUpdated({value: 'asd', type: 'plus-button' }, 0);
-        ctx.scope.tagSegmentUpdated({value: 'server1', type: 'value'}, 2);
-        ctx.scope.tagSegmentUpdated({value: 'key2', type: 'plus-button'}, 3);
-        ctx.scope.tagSegmentUpdated({value: 'value', type: 'value'}, 6);
-        ctx.scope.tagSegmentUpdated(ctx.scope.removeTagFilterSegment, 4);
-      });
-
-      it('should remove all segment after 2 and replace with plus button', function() {
-        expect(ctx.scope.tagSegments.length).to.be(4);
-        expect(ctx.scope.tagSegments[3].type).to.be('plus-button');
-      });
-    });
-
-  });
-});