diff --git a/karma.conf.js b/karma.conf.js
index 569cf845b16..f05b7dcc61a 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -25,6 +25,7 @@ module.exports = function(config) {
browsers: ['PhantomJS'],
captureTimeout: 60000,
singleRun: true,
+ autoWatchBatchDelay: 1000,
});
diff --git a/public/app/plugins/datasource/graphite/addGraphiteFunc.js b/public/app/plugins/datasource/graphite/add_graphite_func.js
similarity index 100%
rename from public/app/plugins/datasource/graphite/addGraphiteFunc.js
rename to public/app/plugins/datasource/graphite/add_graphite_func.js
diff --git a/public/app/plugins/datasource/graphite/datasource.js b/public/app/plugins/datasource/graphite/datasource.js
index d51f9a93280..553a11c2350 100644
--- a/public/app/plugins/datasource/graphite/datasource.js
+++ b/public/app/plugins/datasource/graphite/datasource.js
@@ -5,9 +5,9 @@ define([
'config',
'app/core/utils/datemath',
'./directives',
- './queryCtrl',
- './funcEditor',
- './addGraphiteFunc',
+ './query_ctrl',
+ './func_editor',
+ './add_graphite_func',
],
function (angular, _, $, config, dateMath) {
'use strict';
diff --git a/public/app/plugins/datasource/graphite/funcEditor.js b/public/app/plugins/datasource/graphite/func_editor.js
similarity index 100%
rename from public/app/plugins/datasource/graphite/funcEditor.js
rename to public/app/plugins/datasource/graphite/func_editor.js
diff --git a/public/app/plugins/datasource/graphite/queryCtrl.js b/public/app/plugins/datasource/graphite/query_ctrl.js
similarity index 100%
rename from public/app/plugins/datasource/graphite/queryCtrl.js
rename to public/app/plugins/datasource/graphite/query_ctrl.js
diff --git a/public/app/plugins/datasource/graphite/specs/datasource_specs.ts b/public/app/plugins/datasource/graphite/specs/datasource_specs.ts
new file mode 100644
index 00000000000..8ba7e35b773
--- /dev/null
+++ b/public/app/plugins/datasource/graphite/specs/datasource_specs.ts
@@ -0,0 +1,120 @@
+///
+///
+
+import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
+declare var helpers: any;
+
+describe('graphiteDatasource', function() {
+ var ctx = new helpers.ServiceTestContext();
+
+ beforeEach(angularMocks.module('grafana.services'));
+ beforeEach(ctx.providePhase(['backendSrv']));
+
+ beforeEach(ctx.createService('GraphiteDatasource'));
+ beforeEach(function() {
+ ctx.ds = new ctx.service({ url: [''] });
+ });
+
+ describe('When querying influxdb with one target using query editor target spec', function() {
+ var query = {
+ rangeRaw: { from: 'now-1h', to: 'now' },
+ targets: [{ target: 'prod1.count' }, {target: 'prod2.count'}],
+ maxDataPoints: 500,
+ };
+
+ var results;
+ var requestOptions;
+
+ beforeEach(function() {
+ ctx.backendSrv.datasourceRequest = function(options) {
+ requestOptions = options;
+ return ctx.$q.when({data: [{ target: 'prod1.count', datapoints: [[10, 1], [12,1]] }]});
+ };
+
+ ctx.ds.query(query).then(function(data) { results = data; });
+ ctx.$rootScope.$apply();
+ });
+
+ it('should generate the correct query', function() {
+ expect(requestOptions.url).to.be('/render');
+ });
+
+ it('should query correctly', function() {
+ var params = requestOptions.data.split('&');
+ expect(params).to.contain('target=prod1.count');
+ expect(params).to.contain('target=prod2.count');
+ expect(params).to.contain('from=-1h');
+ expect(params).to.contain('until=now');
+ });
+
+ it('should exclude undefined params', function() {
+ var params = requestOptions.data.split('&');
+ expect(params).to.not.contain('cacheTimeout=undefined');
+ });
+
+ it('should return series list', function() {
+ expect(results.data.length).to.be(1);
+ expect(results.data[0].target).to.be('prod1.count');
+ });
+
+ it('should convert to millisecond resolution', function() {
+ expect(results.data[0].datapoints[0][0]).to.be(10);
+ });
+
+ });
+
+ describe('building graphite params', function() {
+
+ it('should uri escape targets', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: 'prod1.{test,test2}'}, {target: 'prod2.count'}]
+ });
+ expect(results).to.contain('target=prod1.%7Btest%2Ctest2%7D');
+ });
+
+ it('should replace target placeholder', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: 'series1'}, {target: 'series2'}, {target: 'asPercent(#A,#B)'}]
+ });
+ expect(results[2]).to.be('target=asPercent(series1%2Cseries2)');
+ });
+
+ it('should replace target placeholder for hidden series', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: 'series1', hide: true}, {target: 'sumSeries(#A)', hide: true}, {target: 'asPercent(#A,#B)'}]
+ });
+ expect(results[0]).to.be('target=' + encodeURIComponent('asPercent(series1,sumSeries(series1))'));
+ });
+
+ it('should replace target placeholder when nesting query references', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: 'series1'}, {target: 'sumSeries(#A)'}, {target: 'asPercent(#A,#B)'}]
+ });
+ expect(results[2]).to.be('target=' + encodeURIComponent("asPercent(series1,sumSeries(series1))"));
+ });
+
+ it('should fix wrong minute interval parameters', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: "summarize(prod.25m.count, '25m', 'sum')" }]
+ });
+ expect(results[0]).to.be('target=' + encodeURIComponent("summarize(prod.25m.count, '25min', 'sum')"));
+ });
+
+ it('should fix wrong month interval parameters', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: "summarize(prod.5M.count, '5M', 'sum')" }]
+ });
+ expect(results[0]).to.be('target=' + encodeURIComponent("summarize(prod.5M.count, '5mon', 'sum')"));
+ });
+
+ it('should ignore empty targets', function() {
+ var results = ctx.ds.buildGraphiteParams({
+ targets: [{target: 'series1'}, {target: ''}]
+ });
+ expect(results.length).to.be(2);
+ });
+
+ });
+
+});
+
diff --git a/public/app/plugins/datasource/graphite/specs/gfunc_specs.ts b/public/app/plugins/datasource/graphite/specs/gfunc_specs.ts
new file mode 100644
index 00000000000..ec8c5dbe1ad
--- /dev/null
+++ b/public/app/plugins/datasource/graphite/specs/gfunc_specs.ts
@@ -0,0 +1,127 @@
+///
+
+import {describe, beforeEach, it, sinon, expect} from 'test/lib/common';
+
+declare var gfunc: any;
+
+describe('when creating func instance from func names', function() {
+ it('should return func instance', function() {
+ var func = gfunc.createFuncInstance('sumSeries');
+ expect(func).to.be.ok();
+ expect(func.def.name).to.equal('sumSeries');
+ expect(func.def.params.length).to.equal(5);
+ expect(func.def.defaultParams.length).to.equal(1);
+ });
+
+ it('should return func instance with shortName', function() {
+ var func = gfunc.createFuncInstance('sum');
+ expect(func).to.be.ok();
+ });
+
+ it('should return func instance from funcDef', function() {
+ var func = gfunc.createFuncInstance('sum');
+ var func2 = gfunc.createFuncInstance(func.def);
+ expect(func2).to.be.ok();
+ });
+
+ it('func instance should have text representation', function() {
+ var func = gfunc.createFuncInstance('groupByNode');
+ func.params[0] = 5;
+ func.params[1] = 'avg';
+ func.updateText();
+ expect(func.text).to.equal("groupByNode(5, avg)");
+ });
+});
+
+describe('when rendering func instance', function() {
+
+ it('should handle single metric param', function() {
+ var func = gfunc.createFuncInstance('sumSeries');
+ expect(func.render('hello.metric')).to.equal("sumSeries(hello.metric)");
+ });
+
+ it('should include default params if options enable it', function() {
+ var func = gfunc.createFuncInstance('scaleToSeconds', { withDefaultParams: true });
+ expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)");
+ });
+
+ it('should handle int or interval params with number', function() {
+ var func = gfunc.createFuncInstance('movingMedian');
+ func.params[0] = '5';
+ expect(func.render('hello')).to.equal("movingMedian(hello, 5)");
+ });
+
+ it('should handle int or interval params with interval string', function() {
+ var func = gfunc.createFuncInstance('movingMedian');
+ func.params[0] = '5min';
+ expect(func.render('hello')).to.equal("movingMedian(hello, '5min')");
+ });
+
+ it('should handle metric param and int param and string param', function() {
+ var func = gfunc.createFuncInstance('groupByNode');
+ func.params[0] = 5;
+ func.params[1] = 'avg';
+ expect(func.render('hello.metric')).to.equal("groupByNode(hello.metric, 5, 'avg')");
+ });
+
+ it('should handle function with no metric param', function() {
+ var func = gfunc.createFuncInstance('randomWalk');
+ func.params[0] = 'test';
+ expect(func.render(undefined)).to.equal("randomWalk('test')");
+ });
+
+ it('should handle function multiple series params', function() {
+ var func = gfunc.createFuncInstance('asPercent');
+ func.params[0] = '#B';
+ expect(func.render('#A')).to.equal("asPercent(#A, #B)");
+ });
+
+});
+
+describe('when requesting function categories', function() {
+ it('should return function categories', function() {
+ var catIndex = gfunc.getCategories();
+ expect(catIndex.Special.length).to.be.greaterThan(8);
+ });
+});
+
+describe('when updating func param', function() {
+ it('should update param value and update text representation', function() {
+ var func = gfunc.createFuncInstance('summarize', { withDefaultParams: true });
+ func.updateParam('1h', 0);
+ expect(func.params[0]).to.be('1h');
+ expect(func.text).to.be('summarize(1h, sum, false)');
+ });
+
+ it('should parse numbers as float', function() {
+ var func = gfunc.createFuncInstance('scale');
+ func.updateParam('0.001', 0);
+ expect(func.params[0]).to.be('0.001');
+ });
+});
+
+describe('when updating func param with optional second parameter', function() {
+ it('should update value and text', function() {
+ var func = gfunc.createFuncInstance('aliasByNode');
+ func.updateParam('1', 0);
+ expect(func.params[0]).to.be('1');
+ });
+
+ it('should slit text and put value in second param', function() {
+ var func = gfunc.createFuncInstance('aliasByNode');
+ func.updateParam('4,-5', 0);
+ expect(func.params[0]).to.be('4');
+ expect(func.params[1]).to.be('-5');
+ expect(func.text).to.be('aliasByNode(4, -5)');
+ });
+
+ it('should remove second param when empty string is set', function() {
+ var func = gfunc.createFuncInstance('aliasByNode');
+ func.updateParam('4,-5', 0);
+ func.updateParam('', 1);
+ expect(func.params[0]).to.be('4');
+ expect(func.params[1]).to.be(undefined);
+ expect(func.text).to.be('aliasByNode(4)');
+ });
+});
+
diff --git a/public/app/plugins/datasource/graphite/specs/query_ctrl_specs.ts b/public/app/plugins/datasource/graphite/specs/query_ctrl_specs.ts
new file mode 100644
index 00000000000..0b12ea051e0
--- /dev/null
+++ b/public/app/plugins/datasource/graphite/specs/query_ctrl_specs.ts
@@ -0,0 +1,178 @@
+///
+///
+///
+///
+
+import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
+
+declare var gfunc: any;
+declare var helpers: any;
+
+describe('GraphiteQueryCtrl', function() {
+ var ctx = new helpers.ControllerTestContext();
+
+ beforeEach(angularMocks.module('grafana.controllers'));
+ beforeEach(angularMocks.module('grafana.services'));
+ beforeEach(ctx.providePhase());
+ beforeEach(ctx.createControllerPhase('GraphiteQueryCtrl'));
+
+ beforeEach(function() {
+ ctx.scope.target = {target: 'aliasByNode(scaleToSeconds(test.prod.*,1),2)'};
+
+ ctx.scope.datasource = ctx.datasource;
+ ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
+ });
+
+ describe('init', function() {
+ beforeEach(function() {
+ ctx.scope.init();
+ ctx.scope.$digest();
+ });
+
+ it('should validate metric key exists', function() {
+ expect(ctx.scope.datasource.metricFindQuery.getCall(0).args[0]).to.be('test.prod.*');
+ });
+
+ it('should delete last segment if no metrics are found', function() {
+ expect(ctx.scope.segments[2].value).to.be('select metric');
+ });
+
+ it('should parse expression and build function model', function() {
+ expect(ctx.scope.functions.length).to.be(2);
+ });
+ });
+
+ describe('when adding function', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'test.prod.*.count';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ ctx.scope.addFunction(gfunc.getFuncDef('aliasByNode'));
+ });
+
+ it('should add function with correct node number', function() {
+ expect(ctx.scope.functions[0].params[0]).to.be(2);
+ });
+
+ it('should update target', function() {
+ expect(ctx.scope.target.target).to.be('aliasByNode(test.prod.*.count, 2)');
+ });
+
+ it('should call get_data', function() {
+ expect(ctx.scope.$parent.get_data.called).to.be(true);
+ });
+ });
+
+ describe('when adding function before any metric segment', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = '';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: true}]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ ctx.scope.addFunction(gfunc.getFuncDef('asPercent'));
+ });
+
+ it('should add function and remove select metric link', function() {
+ expect(ctx.scope.segments.length).to.be(0);
+ });
+ });
+
+ describe('when initalizing target without metric expression and only function', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'asPercent(#A, #B)';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ });
+
+ it('should not add select metric segment', function() {
+ expect(ctx.scope.segments.length).to.be(0);
+ });
+
+ it('should add both series refs as params', function() {
+ expect(ctx.scope.functions[0].params.length).to.be(2);
+ });
+
+ });
+
+ describe('when initializing a target with single param func using variable', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'movingAverage(prod.count, $var)';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ });
+
+ it('should add 2 segments', function() {
+ expect(ctx.scope.segments.length).to.be(2);
+ });
+
+ it('should add function param', function() {
+ expect(ctx.scope.functions[0].params.length).to.be(1);
+ });
+
+ });
+
+ describe('when initalizing target without metric expression and function with series-ref', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'asPercent(metric.node.count, #A)';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ });
+
+ it('should add segments', function() {
+ expect(ctx.scope.segments.length).to.be(3);
+ });
+
+ it('should have correct func params', function() {
+ expect(ctx.scope.functions[0].params.length).to.be(1);
+ });
+ });
+
+ describe('when getting altSegments and metricFindQuery retuns empty array', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'test.count';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+ ctx.scope.init();
+ ctx.scope.getAltSegments(1).then(function(results) {
+ ctx.altSegments = results;
+ });
+ ctx.scope.$digest();
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ });
+
+ it('should have no segments', function() {
+ expect(ctx.altSegments.length).to.be(0);
+ });
+
+ });
+
+ describe('targetChanged', function() {
+ beforeEach(function() {
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
+ ctx.scope.init();
+ ctx.scope.$digest();
+
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ ctx.scope.target.target = '';
+ ctx.scope.targetChanged();
+ });
+
+ it('should rebuld target after expression model', function() {
+ expect(ctx.scope.target.target).to.be('aliasByNode(scaleToSeconds(test.prod.*, 1), 2)');
+ });
+
+ it('should call get_data', function() {
+ expect(ctx.scope.$parent.get_data.called).to.be(true);
+ });
+ });
+});
diff --git a/public/test/lib/common.ts b/public/test/lib/common.ts
index 53f50301d42..523a97c2c03 100644
--- a/public/test/lib/common.ts
+++ b/public/test/lib/common.ts
@@ -7,10 +7,15 @@ var it = _global.it;
var sinon = _global.sinon;
var expect = _global.expect;
+var angularMocks = {
+ module: _global.module,
+};
+
export {
beforeEach,
describe,
it,
sinon,
- expect
+ expect,
+ angularMocks,
}
diff --git a/public/test/specs/gfunc-specs.js b/public/test/specs/gfunc-specs.js
deleted file mode 100644
index 15096536de5..00000000000
--- a/public/test/specs/gfunc-specs.js
+++ /dev/null
@@ -1,130 +0,0 @@
-define([
- 'app/plugins/datasource/graphite/gfunc'
-], function(gfunc) {
- 'use strict';
-
- describe('when creating func instance from func names', function() {
-
- it('should return func instance', function() {
- var func = gfunc.createFuncInstance('sumSeries');
- expect(func).to.be.ok();
- expect(func.def.name).to.equal('sumSeries');
- expect(func.def.params.length).to.equal(5);
- expect(func.def.defaultParams.length).to.equal(1);
- });
-
- it('should return func instance with shortName', function() {
- var func = gfunc.createFuncInstance('sum');
- expect(func).to.be.ok();
- });
-
- it('should return func instance from funcDef', function() {
- var func = gfunc.createFuncInstance('sum');
- var func2 = gfunc.createFuncInstance(func.def);
- expect(func2).to.be.ok();
- });
-
- it('func instance should have text representation', function() {
- var func = gfunc.createFuncInstance('groupByNode');
- func.params[0] = 5;
- func.params[1] = 'avg';
- func.updateText();
- expect(func.text).to.equal("groupByNode(5, avg)");
- });
-
- });
-
- describe('when rendering func instance', function() {
-
- it('should handle single metric param', function() {
- var func = gfunc.createFuncInstance('sumSeries');
- expect(func.render('hello.metric')).to.equal("sumSeries(hello.metric)");
- });
-
- it('should include default params if options enable it', function() {
- var func = gfunc.createFuncInstance('scaleToSeconds', { withDefaultParams: true });
- expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)");
- });
-
- it('should handle int or interval params with number', function() {
- var func = gfunc.createFuncInstance('movingMedian');
- func.params[0] = '5';
- expect(func.render('hello')).to.equal("movingMedian(hello, 5)");
- });
-
- it('should handle int or interval params with interval string', function() {
- var func = gfunc.createFuncInstance('movingMedian');
- func.params[0] = '5min';
- expect(func.render('hello')).to.equal("movingMedian(hello, '5min')");
- });
-
- it('should handle metric param and int param and string param', function() {
- var func = gfunc.createFuncInstance('groupByNode');
- func.params[0] = 5;
- func.params[1] = 'avg';
- expect(func.render('hello.metric')).to.equal("groupByNode(hello.metric, 5, 'avg')");
- });
-
- it('should handle function with no metric param', function() {
- var func = gfunc.createFuncInstance('randomWalk');
- func.params[0] = 'test';
- expect(func.render(undefined)).to.equal("randomWalk('test')");
- });
-
- it('should handle function multiple series params', function() {
- var func = gfunc.createFuncInstance('asPercent');
- func.params[0] = '#B';
- expect(func.render('#A')).to.equal("asPercent(#A, #B)");
- });
-
- });
-
- describe('when requesting function categories', function() {
- it('should return function categories', function() {
- var catIndex = gfunc.getCategories();
- expect(catIndex.Special.length).to.be.greaterThan(8);
- });
- });
-
- describe('when updating func param', function() {
- it('should update param value and update text representation', function() {
- var func = gfunc.createFuncInstance('summarize', { withDefaultParams: true });
- func.updateParam('1h', 0);
- expect(func.params[0]).to.be('1h');
- expect(func.text).to.be('summarize(1h, sum, false)');
- });
-
- it('should parse numbers as float', function() {
- var func = gfunc.createFuncInstance('scale');
- func.updateParam('0.001', 0);
- expect(func.params[0]).to.be('0.001');
- });
- });
-
- describe('when updating func param with optional second parameter', function() {
- it('should update value and text', function() {
- var func = gfunc.createFuncInstance('aliasByNode');
- func.updateParam('1', 0);
- expect(func.params[0]).to.be('1');
- });
-
- it('should slit text and put value in second param', function() {
- var func = gfunc.createFuncInstance('aliasByNode');
- func.updateParam('4,-5', 0);
- expect(func.params[0]).to.be('4');
- expect(func.params[1]).to.be('-5');
- expect(func.text).to.be('aliasByNode(4, -5)');
- });
-
- it('should remove second param when empty string is set', function() {
- var func = gfunc.createFuncInstance('aliasByNode');
- func.updateParam('4,-5', 0);
- func.updateParam('', 1);
- expect(func.params[0]).to.be('4');
- expect(func.params[1]).to.be(undefined);
- expect(func.text).to.be('aliasByNode(4)');
- });
- });
-
-});
-
diff --git a/public/test/specs/graphiteDatasource-specs.js b/public/test/specs/graphiteDatasource-specs.js
deleted file mode 100644
index 3aacff95efd..00000000000
--- a/public/test/specs/graphiteDatasource-specs.js
+++ /dev/null
@@ -1,122 +0,0 @@
-define([
- './helpers',
- 'app/plugins/datasource/graphite/datasource'
-], function(helpers) {
- 'use strict';
-
- describe('graphiteDatasource', function() {
- var ctx = new helpers.ServiceTestContext();
-
- beforeEach(module('grafana.services'));
- beforeEach(ctx.providePhase(['backendSrv']));
-
- beforeEach(ctx.createService('GraphiteDatasource'));
- beforeEach(function() {
- ctx.ds = new ctx.service({ url: [''] });
- });
-
- describe('When querying influxdb with one target using query editor target spec', function() {
- var query = {
- rangeRaw: { from: 'now-1h', to: 'now' },
- targets: [{ target: 'prod1.count' }, {target: 'prod2.count'}],
- maxDataPoints: 500,
- };
-
- var results;
- var requestOptions;
-
- beforeEach(function() {
- ctx.backendSrv.datasourceRequest = function(options) {
- requestOptions = options;
- return ctx.$q.when({data: [{ target: 'prod1.count', datapoints: [[10, 1], [12,1]] }]});
- };
-
- ctx.ds.query(query).then(function(data) { results = data; });
- ctx.$rootScope.$apply();
- });
-
- it('should generate the correct query', function() {
- expect(requestOptions.url).to.be('/render');
- });
-
- it('should query correctly', function() {
- var params = requestOptions.data.split('&');
- expect(params).to.contain('target=prod1.count');
- expect(params).to.contain('target=prod2.count');
- expect(params).to.contain('from=-1h');
- expect(params).to.contain('until=now');
- });
-
- it('should exclude undefined params', function() {
- var params = requestOptions.data.split('&');
- expect(params).to.not.contain('cacheTimeout=undefined');
- });
-
- it('should return series list', function() {
- expect(results.data.length).to.be(1);
- expect(results.data[0].target).to.be('prod1.count');
- });
-
- it('should convert to millisecond resolution', function() {
- expect(results.data[0].datapoints[0][0]).to.be(10);
- });
-
- });
-
- describe('building graphite params', function() {
-
- it('should uri escape targets', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: 'prod1.{test,test2}'}, {target: 'prod2.count'}]
- });
- expect(results).to.contain('target=prod1.%7Btest%2Ctest2%7D');
- });
-
- it('should replace target placeholder', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: 'series1'}, {target: 'series2'}, {target: 'asPercent(#A,#B)'}]
- });
- expect(results[2]).to.be('target=asPercent(series1%2Cseries2)');
- });
-
- it('should replace target placeholder for hidden series', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: 'series1', hide: true}, {target: 'sumSeries(#A)', hide: true}, {target: 'asPercent(#A,#B)'}]
- });
- expect(results[0]).to.be('target=' + encodeURIComponent('asPercent(series1,sumSeries(series1))'));
- });
-
- it('should replace target placeholder when nesting query references', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: 'series1'}, {target: 'sumSeries(#A)'}, {target: 'asPercent(#A,#B)'}]
- });
- expect(results[2]).to.be('target=' + encodeURIComponent("asPercent(series1,sumSeries(series1))"));
- });
-
- it('should fix wrong minute interval parameters', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: "summarize(prod.25m.count, '25m', 'sum')" }]
- });
- expect(results[0]).to.be('target=' + encodeURIComponent("summarize(prod.25m.count, '25min', 'sum')"));
- });
-
- it('should fix wrong month interval parameters', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: "summarize(prod.5M.count, '5M', 'sum')" }]
- });
- expect(results[0]).to.be('target=' + encodeURIComponent("summarize(prod.5M.count, '5mon', 'sum')"));
- });
-
- it('should ignore empty targets', function() {
- var results = ctx.ds.buildGraphiteParams({
- targets: [{target: 'series1'}, {target: ''}]
- });
- expect(results.length).to.be(2);
- });
-
- });
-
- });
-
-});
-
diff --git a/public/test/specs/graphiteTargetCtrl-specs.js b/public/test/specs/graphiteTargetCtrl-specs.js
deleted file mode 100644
index 42d97ea5fa2..00000000000
--- a/public/test/specs/graphiteTargetCtrl-specs.js
+++ /dev/null
@@ -1,179 +0,0 @@
-define([
- './helpers',
- 'app/plugins/datasource/graphite/gfunc',
- 'app/plugins/datasource/graphite/queryCtrl',
- 'app/services/uiSegmentSrv'
-], function(helpers, gfunc) {
- 'use strict';
-
- describe('GraphiteQueryCtrl', function() {
- var ctx = new helpers.ControllerTestContext();
-
- beforeEach(module('grafana.controllers'));
- beforeEach(module('grafana.services'));
- beforeEach(ctx.providePhase());
- beforeEach(ctx.createControllerPhase('GraphiteQueryCtrl'));
-
- beforeEach(function() {
- ctx.scope.target = {target: 'aliasByNode(scaleToSeconds(test.prod.*,1),2)'};
-
- ctx.scope.datasource = ctx.datasource;
- ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
- });
-
- describe('init', function() {
- beforeEach(function() {
- ctx.scope.init();
- ctx.scope.$digest();
- });
-
- it('should validate metric key exists', function() {
- expect(ctx.scope.datasource.metricFindQuery.getCall(0).args[0]).to.be('test.prod.*');
- });
-
- it('should delete last segment if no metrics are found', function() {
- expect(ctx.scope.segments[2].value).to.be('select metric');
- });
-
- it('should parse expression and build function model', function() {
- expect(ctx.scope.functions.length).to.be(2);
- });
- });
-
- describe('when adding function', function() {
- beforeEach(function() {
- ctx.scope.target.target = 'test.prod.*.count';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
- ctx.scope.init();
- ctx.scope.$digest();
-
- ctx.scope.$parent = { get_data: sinon.spy() };
- ctx.scope.addFunction(gfunc.getFuncDef('aliasByNode'));
- });
-
- it('should add function with correct node number', function() {
- expect(ctx.scope.functions[0].params[0]).to.be(2);
- });
-
- it('should update target', function() {
- expect(ctx.scope.target.target).to.be('aliasByNode(test.prod.*.count, 2)');
- });
-
- it('should call get_data', function() {
- expect(ctx.scope.$parent.get_data.called).to.be(true);
- });
- });
-
- describe('when adding function before any metric segment', function() {
- beforeEach(function() {
- ctx.scope.target.target = '';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: true}]));
- ctx.scope.init();
- ctx.scope.$digest();
-
- ctx.scope.$parent = { get_data: sinon.spy() };
- ctx.scope.addFunction(gfunc.getFuncDef('asPercent'));
- });
-
- it('should add function and remove select metric link', function() {
- expect(ctx.scope.segments.length).to.be(0);
- });
- });
-
- describe('when initalizing target without metric expression and only function', function() {
- beforeEach(function() {
- ctx.scope.target.target = 'asPercent(#A, #B)';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
- ctx.scope.init();
- ctx.scope.$digest();
- ctx.scope.$parent = { get_data: sinon.spy() };
- });
-
- it('should not add select metric segment', function() {
- expect(ctx.scope.segments.length).to.be(0);
- });
-
- it('should add both series refs as params', function() {
- expect(ctx.scope.functions[0].params.length).to.be(2);
- });
-
- });
-
- describe('when initializing a target with single param func using variable', function() {
- beforeEach(function() {
- ctx.scope.target.target = 'movingAverage(prod.count, $var)';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
- ctx.scope.init();
- ctx.scope.$digest();
- ctx.scope.$parent = { get_data: sinon.spy() };
- });
-
- it('should add 2 segments', function() {
- expect(ctx.scope.segments.length).to.be(2);
- });
-
- it('should add function param', function() {
- expect(ctx.scope.functions[0].params.length).to.be(1);
- });
-
- });
-
- describe('when initalizing target without metric expression and function with series-ref', function() {
- beforeEach(function() {
- ctx.scope.target.target = 'asPercent(metric.node.count, #A)';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
- ctx.scope.init();
- ctx.scope.$digest();
- ctx.scope.$parent = { get_data: sinon.spy() };
- });
-
- it('should add segments', function() {
- expect(ctx.scope.segments.length).to.be(3);
- });
-
- it('should have correct func params', function() {
- expect(ctx.scope.functions[0].params.length).to.be(1);
- });
- });
-
- describe('when getting altSegments and metricFindQuery retuns empty array', function() {
- beforeEach(function() {
- ctx.scope.target.target = 'test.count';
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
- ctx.scope.init();
- ctx.scope.getAltSegments(1).then(function(results) {
- ctx.altSegments = results;
- });
- ctx.scope.$digest();
- ctx.scope.$parent = { get_data: sinon.spy() };
- });
-
- it('should have no segments', function() {
- expect(ctx.altSegments.length).to.be(0);
- });
-
- });
-
- describe('targetChanged', function() {
- beforeEach(function() {
- ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
- ctx.scope.init();
- ctx.scope.$digest();
-
- ctx.scope.$parent = { get_data: sinon.spy() };
- ctx.scope.target.target = '';
- ctx.scope.targetChanged();
- });
-
- it('should rebuld target after expression model', function() {
- expect(ctx.scope.target.target).to.be('aliasByNode(scaleToSeconds(test.prod.*, 1), 2)');
- });
-
- it('should call get_data', function() {
- expect(ctx.scope.$parent.get_data.called).to.be(true);
- });
- });
-
-
- });
-});
diff --git a/public/test/test-main.js b/public/test/test-main.js
index 4c5d63ede2e..5a7f1eeb437 100644
--- a/public/test/test-main.js
+++ b/public/test/test-main.js
@@ -113,7 +113,7 @@ require([
var specs = [];
for (var file in window.__karma__.files) {
- if (/base\/test\/specs.*/.test(file)) {
+ if (/specs.*/.test(file)) {
file = file2moduleName(file);
specs.push(file);
}