Files
grafana/public/app/plugins/datasource/loki/datasource.test.ts
2019-09-10 11:04:44 +02:00

266 lines
7.8 KiB
TypeScript

import LokiDatasource from './datasource';
import { LokiQuery } from './types';
import { getQueryOptions } from 'test/helpers/getQueryOptions';
import { AnnotationQueryRequest, DataSourceApi } from '@grafana/ui';
import { DataFrame, dateTime } from '@grafana/data';
import { BackendSrv } from 'app/core/services/backend_srv';
import { TemplateSrv } from 'app/features/templating/template_srv';
describe('LokiDatasource', () => {
const instanceSettings: any = {
url: 'myloggingurl',
};
const testResp = {
data: {
streams: [
{
entries: [{ ts: '2019-02-01T10:27:37.498180581Z', line: 'hello' }],
labels: '{}',
},
],
},
};
const backendSrvMock = { datasourceRequest: jest.fn() };
const backendSrv = (backendSrvMock as unknown) as BackendSrv;
const templateSrvMock = ({
getAdhocFilters: (): any[] => [],
replace: (a: string) => a,
} as unknown) as TemplateSrv;
describe('when querying', () => {
const testLimit = makeLimitTest(instanceSettings, backendSrvMock, backendSrv, templateSrvMock, testResp);
test('should use default max lines when no limit given', () => {
testLimit({
expectedLimit: 1000,
});
});
test('should use custom max lines if limit is set', () => {
testLimit({
maxLines: 20,
expectedLimit: 20,
});
});
test('should use custom maxDataPoints if set in request', () => {
testLimit({
maxDataPoints: 500,
expectedLimit: 500,
});
});
test('should use datasource maxLimit if maxDataPoints is higher', () => {
testLimit({
maxLines: 20,
maxDataPoints: 500,
expectedLimit: 20,
});
});
test('should return series data', async done => {
const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 };
const customSettings = { ...instanceSettings, jsonData: customData };
const ds = new LokiDatasource(customSettings, backendSrv, templateSrvMock);
backendSrvMock.datasourceRequest = jest.fn(() => Promise.resolve(testResp));
const options = getQueryOptions<LokiQuery>({
targets: [{ expr: '{} foo', refId: 'B' }],
});
const res = await ds.query(options);
const dataFrame = res.data[0] as DataFrame;
expect(dataFrame.fields[1].values.get(0)).toBe('hello');
expect(dataFrame.meta.limit).toBe(20);
expect(dataFrame.meta.searchWords).toEqual(['(?i)foo']);
done();
});
});
describe('when performing testDataSource', () => {
let ds: DataSourceApi<any, any>;
let result: any;
describe('and call succeeds', () => {
beforeEach(async () => {
const backendSrv = ({
async datasourceRequest() {
return Promise.resolve({
status: 200,
data: {
values: ['avalue'],
},
});
},
} as unknown) as BackendSrv;
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
result = await ds.testDatasource();
});
it('should return successfully', () => {
expect(result.status).toBe('success');
});
});
describe('and call fails with 401 error', () => {
beforeEach(async () => {
const backendSrv = ({
async datasourceRequest() {
return Promise.reject({
statusText: 'Unauthorized',
status: 401,
data: {
message: 'Unauthorized',
},
});
},
} as unknown) as BackendSrv;
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
result = await ds.testDatasource();
});
it('should return error status and a detailed error message', () => {
expect(result.status).toEqual('error');
expect(result.message).toBe('Loki: Unauthorized. 401. Unauthorized');
});
});
describe('and call fails with 404 error', () => {
beforeEach(async () => {
const backendSrv = ({
async datasourceRequest() {
return Promise.reject({
statusText: 'Not found',
status: 404,
data: '404 page not found',
});
},
} as unknown) as BackendSrv;
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
result = await ds.testDatasource();
});
it('should return error status and a detailed error message', () => {
expect(result.status).toEqual('error');
expect(result.message).toBe('Loki: Not found. 404. 404 page not found');
});
});
describe('and call fails with 502 error', () => {
beforeEach(async () => {
const backendSrv = ({
async datasourceRequest() {
return Promise.reject({
statusText: 'Bad Gateway',
status: 502,
data: '',
});
},
} as unknown) as BackendSrv;
ds = new LokiDatasource(instanceSettings, backendSrv, {} as TemplateSrv);
result = await ds.testDatasource();
});
it('should return error status and a detailed error message', () => {
expect(result.status).toEqual('error');
expect(result.message).toBe('Loki: Bad Gateway. 502');
});
});
});
describe('annotationQuery', () => {
it('should transform the loki data to annototion response', async () => {
const ds = new LokiDatasource(instanceSettings, backendSrv, templateSrvMock);
backendSrvMock.datasourceRequest = jest.fn(() =>
Promise.resolve({
data: {
streams: [
{
entries: [{ ts: '2019-02-01T10:27:37.498180581Z', line: 'hello' }],
labels: '{label="value"}',
},
{
entries: [{ ts: '2019-02-01T12:27:37.498180581Z', line: 'hello 2' }],
labels: '{label2="value2"}',
},
],
},
})
);
const query = makeAnnotationQueryRequest();
const res = await ds.annotationQuery(query);
expect(res.length).toBe(2);
expect(res[0].text).toBe('hello');
expect(res[0].tags).toEqual(['value']);
expect(res[1].text).toBe('hello 2');
expect(res[1].tags).toEqual(['value2']);
});
});
});
type LimitTestArgs = {
maxDataPoints?: number;
maxLines?: number;
expectedLimit: number;
};
function makeLimitTest(
instanceSettings: any,
backendSrvMock: any,
backendSrv: any,
templateSrvMock: any,
testResp: any
) {
return ({ maxDataPoints, maxLines, expectedLimit }: LimitTestArgs) => {
let settings = instanceSettings;
if (Number.isFinite(maxLines)) {
const customData = { ...(instanceSettings.jsonData || {}), maxLines: 20 };
settings = { ...instanceSettings, jsonData: customData };
}
const ds = new LokiDatasource(settings, backendSrv, templateSrvMock);
backendSrvMock.datasourceRequest = jest.fn(() => Promise.resolve(testResp));
const options = getQueryOptions<LokiQuery>({ targets: [{ expr: 'foo', refId: 'B' }] });
if (Number.isFinite(maxDataPoints)) {
options.maxDataPoints = maxDataPoints;
} else {
// By default is 500
delete options.maxDataPoints;
}
ds.query(options);
expect(backendSrvMock.datasourceRequest.mock.calls.length).toBe(1);
expect(backendSrvMock.datasourceRequest.mock.calls[0][0].url).toContain(`limit=${expectedLimit}`);
};
}
function makeAnnotationQueryRequest(): AnnotationQueryRequest<LokiQuery> {
const timeRange = {
from: dateTime(),
to: dateTime(),
};
return {
annotation: {
expr: '{test=test}',
refId: '',
datasource: 'loki',
enable: true,
name: 'test-annotation',
},
dashboard: {
id: 1,
} as any,
range: {
...timeRange,
raw: timeRange,
},
rangeRaw: timeRange,
};
}