文件操作 - datasource.test.ts
返回文件管理
返回主菜单
删除本文件
文件: /usr/share/grafana/public/app/plugins/datasource/graphite/specs/datasource.test.ts
编辑文件内容
import { GraphiteDatasource } from '../datasource'; import _ from 'lodash'; import { TemplateSrv } from 'app/features/templating/template_srv'; import { dateTime, getFrameDisplayName } from '@grafana/data'; import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__ jest.mock('@grafana/runtime', () => ({ ...((jest.requireActual('@grafana/runtime') as unknown) as object), getBackendSrv: () => backendSrv, })); interface Context { templateSrv: TemplateSrv; ds: GraphiteDatasource; } describe('graphiteDatasource', () => { const datasourceRequestMock = jest.spyOn(backendSrv, 'datasourceRequest'); let ctx = {} as Context; beforeEach(() => { jest.clearAllMocks(); const instanceSettings = { url: '/api/datasources/proxy/1', name: 'graphiteProd', jsonData: { rollupIndicatorEnabled: true, }, }; const templateSrv = new TemplateSrv(); const ds = new GraphiteDatasource(instanceSettings, templateSrv); ctx = { templateSrv, ds }; }); describe('convertResponseToDataFrames', () => { it('should transform regular result', () => { const result = ctx.ds.convertResponseToDataFrames({ data: { meta: { stats: { 'executeplan.cache-hit-partial.count': 5, 'executeplan.cache-hit.count': 10, }, }, series: [ { target: 'seriesA', datapoints: [ [100, 200], [101, 201], ], meta: [ { 'aggnum-norm': 1, 'aggnum-rc': 7, 'archive-interval': 3600, 'archive-read': 1, 'consolidator-normfetch': 'AverageConsolidator', 'consolidator-rc': 'AverageConsolidator', count: 1, 'schema-name': 'wpUsageMetrics', 'schema-retentions': '1h:35d:6h:2,2h:2y:6h:2', }, ], }, { target: 'seriesB', meta: [ { 'aggnum-norm': 1, 'aggnum-rc': 0, 'archive-interval': 3600, 'archive-read': 0, 'consolidator-normfetch': 'AverageConsolidator', 'consolidator-rc': 'NoneConsolidator', count: 1, 'schema-name': 'wpUsageMetrics', 'schema-retentions': '1h:35d:6h:2,2h:2y:6h:2', }, ], datapoints: [ [200, 300], [201, 301], ], }, ], }, }); expect(result.data.length).toBe(2); expect(getFrameDisplayName(result.data[0])).toBe('seriesA'); expect(getFrameDisplayName(result.data[1])).toBe('seriesB'); expect(result.data[0].length).toBe(2); expect(result.data[0].meta.notices.length).toBe(1); expect(result.data[0].meta.notices[0].text).toBe('Data is rolled up, aggregated over 2h using Average function'); expect(result.data[1].meta.notices).toBeUndefined(); }); }); describe('When querying graphite with one target using query editor target spec', () => { const query = { panelId: 3, dashboardId: 5, rangeRaw: { from: 'now-1h', to: 'now' }, targets: [{ target: 'prod1.count' }, { target: 'prod2.count' }], maxDataPoints: 500, }; let results: any; let requestOptions: any; beforeEach(async () => { datasourceRequestMock.mockImplementation((options: any) => { requestOptions = options; return Promise.resolve({ data: [ { target: 'prod1.count', datapoints: [ [10, 1], [12, 1], ], }, ], }); }); await ctx.ds.query(query as any).then((data: any) => { results = data; }); }); it('X-Dashboard and X-Panel headers to be set!', () => { expect(requestOptions.headers['X-Dashboard-Id']).toBe(5); expect(requestOptions.headers['X-Panel-Id']).toBe(3); }); it('should generate the correct query', () => { expect(requestOptions.url).toBe('/api/datasources/proxy/1/render'); }); it('should set unique requestId', () => { expect(requestOptions.requestId).toBe('graphiteProd.panelId.3'); }); it('should query correctly', () => { const params = requestOptions.data.split('&'); expect(params).toContain('target=prod1.count'); expect(params).toContain('target=prod2.count'); expect(params).toContain('from=-1h'); expect(params).toContain('until=now'); }); it('should exclude undefined params', () => { const params = requestOptions.data.split('&'); expect(params).not.toContain('cacheTimeout=undefined'); }); it('should return series list', () => { expect(results.data.length).toBe(1); expect(results.data[0].name).toBe('prod1.count'); }); it('should convert to millisecond resolution', () => { expect(results.data[0].fields[1].values.get(0)).toBe(10); }); }); describe('when fetching Graphite Events as annotations', () => { let results: any; const options = { annotation: { tags: 'tag1', }, range: { from: dateTime(1432288354), to: dateTime(1432288401), }, rangeRaw: { from: 'now-24h', to: 'now' }, }; describe('and tags are returned as string', () => { const response = { data: [ { when: 1507222850, tags: 'tag1 tag2', data: 'some text', id: 2, what: 'Event - deploy', }, ], }; beforeEach(async () => { datasourceRequestMock.mockImplementation((options: any) => { return Promise.resolve(response); }); await ctx.ds.annotationQuery(options).then((data: any) => { results = data; }); }); it('should parse the tags string into an array', () => { expect(_.isArray(results[0].tags)).toEqual(true); expect(results[0].tags.length).toEqual(2); expect(results[0].tags[0]).toEqual('tag1'); expect(results[0].tags[1]).toEqual('tag2'); }); }); describe('and tags are returned as an array', () => { const response = { data: [ { when: 1507222850, tags: ['tag1', 'tag2'], data: 'some text', id: 2, what: 'Event - deploy', }, ], }; beforeEach(() => { datasourceRequestMock.mockImplementation((options: any) => { return Promise.resolve(response); }); ctx.ds.annotationQuery(options).then((data: any) => { results = data; }); // ctx.$rootScope.$apply(); }); it('should parse the tags string into an array', () => { expect(_.isArray(results[0].tags)).toEqual(true); expect(results[0].tags.length).toEqual(2); expect(results[0].tags[0]).toEqual('tag1'); expect(results[0].tags[1]).toEqual('tag2'); }); }); }); describe('building graphite params', () => { it('should return empty array if no targets', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{}], }); expect(results.length).toBe(0); }); it('should uri escape targets', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'prod1.{test,test2}' }, { target: 'prod2.count' }], }); expect(results).toContain('target=prod1.%7Btest%2Ctest2%7D'); }); it('should replace target placeholder', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'series1' }, { target: 'series2' }, { target: 'asPercent(#A,#B)' }], }); expect(results[2]).toBe('target=asPercent(series1%2Cseries2)'); }); it('should replace target placeholder for hidden series', () => { const results = ctx.ds.buildGraphiteParams({ targets: [ { target: 'series1', hide: true }, { target: 'sumSeries(#A)', hide: true }, { target: 'asPercent(#A,#B)' }, ], }); expect(results[0]).toBe('target=' + encodeURIComponent('asPercent(series1,sumSeries(series1))')); }); it('should replace target placeholder when nesting query references', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'series1' }, { target: 'sumSeries(#A)' }, { target: 'asPercent(#A,#B)' }], }); expect(results[2]).toBe('target=' + encodeURIComponent('asPercent(series1,sumSeries(series1))')); }); it('should fix wrong minute interval parameters', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: "summarize(prod.25m.count, '25m', 'sum')" }], }); expect(results[0]).toBe('target=' + encodeURIComponent("summarize(prod.25m.count, '25min', 'sum')")); }); it('should fix wrong month interval parameters', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: "summarize(prod.5M.count, '5M', 'sum')" }], }); expect(results[0]).toBe('target=' + encodeURIComponent("summarize(prod.5M.count, '5mon', 'sum')")); }); it('should ignore empty targets', () => { const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'series1' }, { target: '' }], }); expect(results.length).toBe(2); }); describe('when formatting targets', () => { it('does not attempt to glob for one variable', () => { ctx.templateSrv.init([ { type: 'query', name: 'metric', current: { value: ['b'] }, }, ]); const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'my.$metric.*' }], }); expect(results).toStrictEqual(['target=my.b.*', 'format=json']); }); it('globs for more than one variable', () => { ctx.templateSrv.init([ { type: 'query', name: 'metric', current: { value: ['a', 'b'] }, }, ]); const results = ctx.ds.buildGraphiteParams({ targets: [{ target: 'my.[[metric]].*' }], }); expect(results).toStrictEqual(['target=my.%7Ba%2Cb%7D.*', 'format=json']); }); }); }); describe('querying for template variables', () => { let results: any; let requestOptions: any; beforeEach(() => { datasourceRequestMock.mockImplementation((options: any) => { requestOptions = options; return Promise.resolve({ data: ['backend_01', 'backend_02'], }); }); }); it('should generate tags query', () => { ctx.ds.metricFindQuery('tags()').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); }); it('should generate tags query with a filter expression', () => { ctx.ds.metricFindQuery('tags(server=backend_01)').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual(['server=backend_01']); expect(results).not.toBe(null); }); it('should generate tags query for an expression with whitespace after', () => { ctx.ds.metricFindQuery('tags(server=backend_01 )').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual(['server=backend_01']); expect(results).not.toBe(null); }); it('should generate tag values query for one tag', () => { ctx.ds.metricFindQuery('tag_values(server)').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); }); it('should generate tag values query for a tag and expression', () => { ctx.ds.metricFindQuery('tag_values(server,server=~backend*)').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual(['server=~backend*']); expect(results).not.toBe(null); }); it('should generate tag values query for a tag with whitespace after', () => { ctx.ds.metricFindQuery('tag_values(server )').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); }); it('should generate tag values query for a tag and expression with whitespace after', () => { ctx.ds.metricFindQuery('tag_values(server , server=~backend* )').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual(['server=~backend*']); expect(results).not.toBe(null); }); it('/metrics/find should be POST', () => { ctx.templateSrv.init([ { type: 'query', name: 'foo', current: { value: ['bar'] }, }, ]); ctx.ds.metricFindQuery('[[foo]]').then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/metrics/find'); expect(requestOptions.method).toEqual('POST'); expect(requestOptions.headers).toHaveProperty('Content-Type', 'application/x-www-form-urlencoded'); expect(requestOptions.data).toMatch(`query=bar`); expect(requestOptions).toHaveProperty('params'); }); it('should interpolate $__searchFilter with searchFilter', () => { ctx.ds.metricFindQuery('app.$__searchFilter', { searchFilter: 'backend' }).then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/metrics/find'); expect(requestOptions.params).toEqual({}); expect(requestOptions.data).toEqual('query=app.backend*'); expect(results).not.toBe(null); }); it('should interpolate $__searchFilter with default when searchFilter is missing', () => { ctx.ds.metricFindQuery('app.$__searchFilter', {}).then((data: any) => { results = data; }); expect(requestOptions.url).toBe('/api/datasources/proxy/1/metrics/find'); expect(requestOptions.params).toEqual({}); expect(requestOptions.data).toEqual('query=app.*'); expect(results).not.toBe(null); }); }); }); function accessScenario(name: string, url: string, fn: any) { describe('access scenario ' + name, () => { const ctx: any = { // @ts-ignore templateSrv: new TemplateSrv(), instanceSettings: { url: 'url', name: 'graphiteProd', jsonData: {} }, }; const httpOptions = { headers: {}, }; describe('when using proxy mode', () => { const options = { dashboardId: 1, panelId: 2 }; it('tracing headers should be added', () => { ctx.instanceSettings.url = url; const ds = new GraphiteDatasource(ctx.instanceSettings, ctx.templateSrv); ds.addTracingHeaders(httpOptions, options); fn(httpOptions); }); }); }); } accessScenario('with proxy access', '/api/datasources/proxy/1', (httpOptions: any) => { expect(httpOptions.headers['X-Dashboard-Id']).toBe(1); expect(httpOptions.headers['X-Panel-Id']).toBe(2); }); accessScenario('with direct access', 'http://localhost:8080', (httpOptions: any) => { expect(httpOptions.headers['X-Dashboard-Id']).toBe(undefined); expect(httpOptions.headers['X-Panel-Id']).toBe(undefined); });
修改文件时间
将文件时间修改为当前时间的前一年
删除文件