diff --git a/public/app/plugins/datasource/influxdb/datasource.js b/public/app/plugins/datasource/influxdb/datasource.js
index b9ae9069323..d6a5ccc37ad 100644
--- a/public/app/plugins/datasource/influxdb/datasource.js
+++ b/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';
diff --git a/public/app/plugins/datasource/influxdb/influxSeries.js b/public/app/plugins/datasource/influxdb/influx_series.js
similarity index 100%
rename from public/app/plugins/datasource/influxdb/influxSeries.js
rename to public/app/plugins/datasource/influxdb/influx_series.js
diff --git a/public/app/plugins/datasource/influxdb/queryBuilder.js b/public/app/plugins/datasource/influxdb/query_builder.js
similarity index 100%
rename from public/app/plugins/datasource/influxdb/queryBuilder.js
rename to public/app/plugins/datasource/influxdb/query_builder.js
diff --git a/public/app/plugins/datasource/influxdb/queryCtrl.js b/public/app/plugins/datasource/influxdb/query_ctrl.js
similarity index 99%
rename from public/app/plugins/datasource/influxdb/queryCtrl.js
rename to public/app/plugins/datasource/influxdb/query_ctrl.js
index 5df07d678b4..75dd972fbaa 100644
--- a/public/app/plugins/datasource/influxdb/queryCtrl.js
+++ b/public/app/plugins/datasource/influxdb/query_ctrl.js
@@ -1,7 +1,7 @@
define([
'angular',
'lodash',
- './queryBuilder',
+ './query_builder',
],
function (angular, _, InfluxQueryBuilder) {
'use strict';
diff --git a/public/app/plugins/datasource/influxdb/specs/influx_series_specs.ts b/public/app/plugins/datasource/influxdb/specs/influx_series_specs.ts
new file mode 100644
index 00000000000..c8c127ed759
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/specs/influx_series_specs.ts
@@ -0,0 +1,190 @@
+///
+
+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');
+ });
+ });
+
+});
+
diff --git a/public/app/plugins/datasource/influxdb/specs/query_builder_specs.ts b/public/app/plugins/datasource/influxdb/specs/query_builder_specs.ts
new file mode 100644
index 00000000000..024712341cc
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/specs/query_builder_specs.ts
@@ -0,0 +1,186 @@
+///
+//
+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"');
+ });
+
+ });
+
+});
diff --git a/public/app/plugins/datasource/influxdb/specs/query_ctrl_specs.ts b/public/app/plugins/datasource/influxdb/specs/query_ctrl_specs.ts
new file mode 100644
index 00000000000..ee02338c3da
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/specs/query_ctrl_specs.ts
@@ -0,0 +1,188 @@
+///
+///
+///
+
+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');
+ });
+ });
+
+});
diff --git a/public/test/specs/influx09-querybuilder-specs.js b/public/test/specs/influx09-querybuilder-specs.js
deleted file mode 100644
index 7dd4f4b4ad9..00000000000
--- a/public/test/specs/influx09-querybuilder-specs.js
+++ /dev/null
@@ -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"');
- });
-
- });
-
- });
-
-});
diff --git a/public/test/specs/influxSeries-specs.js b/public/test/specs/influxSeries-specs.js
deleted file mode 100644
index 0c6d786392d..00000000000
--- a/public/test/specs/influxSeries-specs.js
+++ /dev/null
@@ -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');
- });
- });
- });
-
-});
diff --git a/public/test/specs/influxdbQueryCtrl-specs.js b/public/test/specs/influxdbQueryCtrl-specs.js
deleted file mode 100644
index 2d05a032fd6..00000000000
--- a/public/test/specs/influxdbQueryCtrl-specs.js
+++ /dev/null
@@ -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');
- });
- });
-
- });
-});