import {Datasource} from "../module"; import {zabbixTemplateFormat} from "../datasource"; import Q from "q"; import sinon from 'sinon'; import _ from 'lodash'; describe('ZabbixDatasource', () => { let ctx = {}; let defined = sinon.match.defined; beforeEach(() => { ctx.instanceSettings = { jsonData: { username: 'zabbix', password: 'zabbix', trends: true, trendsFrom: '14d', trendsRange: '7d', dbConnection: { enabled: false } } }; ctx.templateSrv = {}; ctx.alertSrv = {}; ctx.dashboardSrv = {}; ctx.zabbixAlertingSrv = {}; ctx.zabbix = () => {}; ctx.ds = new Datasource(ctx.instanceSettings, ctx.templateSrv, ctx.alertSrv, ctx.dashboardSrv, ctx.zabbixAlertingSrv, ctx.zabbix); ctx.ds.alertQuery = () => Q.when([]); }); describe('When querying data', () => { beforeEach(() => { ctx.ds.replaceTemplateVars = (str) => str; }); ctx.options = { targets: [ { group: {filter: ""}, host: {filter: ""}, application: {filter: ""}, item: {filter: ""} } ], range: {from: 'now-7d', to: 'now'} }; it('should return an empty array when no targets are set', (done) => { let options = { targets: [], range: {from: 'now-6h', to: 'now'} }; ctx.ds.query(options).then(result => { expect(result.data).to.have.length(0); done(); }); }); it('should use trends if it enabled and time more than trendsFrom', (done) => { let ranges = ['now-7d', 'now-168h', 'now-1M', 'now-1y']; _.forEach(ranges, range => { ctx.options.range.from = range; ctx.ds.queryNumericData = sinon.spy(); ctx.ds.query(ctx.options); // Check that useTrends options is true expect(ctx.ds.queryNumericData) .to.have.been.calledWith(defined, defined, true); }); done(); }); it('shouldnt use trends if it enabled and time less than trendsFrom', (done) => { let ranges = ['now-6d', 'now-167h', 'now-1h', 'now-30m', 'now-30s']; _.forEach(ranges, range => { ctx.options.range.from = range; ctx.ds.queryNumericData = sinon.spy(); ctx.ds.query(ctx.options); // Check that useTrends options is false expect(ctx.ds.queryNumericData) .to.have.been.calledWith(defined, defined, false); }); done(); }); }); describe('When replacing template variables', () => { function testReplacingVariable(target, varValue, expectedResult, done) { ctx.ds.templateSrv.replace = () => { return zabbixTemplateFormat(varValue); }; let result = ctx.ds.replaceTemplateVars(target); expect(result).to.equal(expectedResult); done(); } /* * Alphanumerics, spaces, dots, dashes and underscores * are allowed in Zabbix host name. * 'AaBbCc0123 .-_' */ it('should return properly escaped regex', (done) => { let target = '$host'; let template_var_value = 'AaBbCc0123 .-_'; let expected_result = '/^AaBbCc0123 \\.-_$/'; testReplacingVariable(target, template_var_value, expected_result, done); }); /* * Single-value variable * $host = backend01 * $host => /^backend01|backend01$/ */ it('should return proper regex for single value', (done) => { let target = '$host'; let template_var_value = 'backend01'; let expected_result = '/^backend01$/'; testReplacingVariable(target, template_var_value, expected_result, done); }); /* * Multi-value variable * $host = [backend01, backend02] * $host => /^(backend01|backend01)$/ */ it('should return proper regex for multi-value', (done) => { let target = '$host'; let template_var_value = ['backend01', 'backend02']; let expected_result = '/^(backend01|backend02)$/'; testReplacingVariable(target, template_var_value, expected_result, done); }); }); describe('When invoking metricFindQuery()', () => { beforeEach(() => { ctx.ds.replaceTemplateVars = (str) => str; ctx.ds.zabbix = { getGroups: () => Q.when([]), getHosts: () => Q.when([]), getApps: () => Q.when([]), getItems: () => Q.when([]) }; }); it('should return groups', (done) => { const tests = [ {query: '*', expect: '/.*/'}, {query: '', expect: ''}, {query: 'Backend', expect: 'Backend'}, {query: 'Back*', expect: 'Back*'} ]; let getGroups = sinon.spy(ctx.ds.zabbix, 'getGroups'); for (const test of tests) { ctx.ds.metricFindQuery(test.query); expect(getGroups).to.have.been.calledWith(test.expect); getGroups.reset(); } done(); }); it('should return hosts', (done) => { const tests = [ {query: '*.*', expect: '/.*/'}, {query: '.', expect: ''}, {query: 'Backend.*', expect: 'Backend'}, {query: 'Back*.', expect: 'Back*'} ]; let getHosts = sinon.spy(ctx.ds.zabbix, 'getHosts'); for (const test of tests) { ctx.ds.metricFindQuery(test.query); expect(getHosts).to.have.been.calledWith(test.expect); getHosts.reset(); } done(); }); it('should return applications', (done) => { const tests = [ {query: '*.*.*', expect: ['/.*/', '/.*/']}, {query: '.*.', expect: ['', '/.*/']}, {query: 'Backend.backend01.*', expect: ['Backend', 'backend01']}, {query: 'Back*.*.', expect: ['Back*', '/.*/']} ]; let getApps = sinon.spy(ctx.ds.zabbix, 'getApps'); for (const test of tests) { ctx.ds.metricFindQuery(test.query); expect(getApps).to.have.been.calledWith(test.expect[0], test.expect[1]); getApps.reset(); } done(); }); it('should return items', (done) => { const tests = [ {query: '*.*.*.*', expect: ['/.*/', '/.*/', '']}, {query: '.*.*.*', expect: ['', '/.*/', '']}, {query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', '']}, {query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu']} ]; let getItems = sinon.spy(ctx.ds.zabbix, 'getItems'); for (const test of tests) { ctx.ds.metricFindQuery(test.query); expect(getItems) .to.have.been.calledWith(test.expect[0], test.expect[1], test.expect[2]); getItems.reset(); } done(); }); it('should invoke method with proper arguments', (done) => { let query = '*.*'; let getHosts = sinon.spy(ctx.ds.zabbix, 'getHosts'); ctx.ds.metricFindQuery(query); expect(getHosts).to.have.been.calledWith('/.*/'); done(); }); }); });