|
|
@@ -1,7 +1,8 @@
|
|
|
// @ts-ignore
|
|
|
import Plain from 'slate-plain-serializer';
|
|
|
|
|
|
-import LanguageProvider, { LABEL_REFRESH_INTERVAL } from './language_provider';
|
|
|
+import LanguageProvider, { LABEL_REFRESH_INTERVAL, rangeToParams } from './language_provider';
|
|
|
+import { AbsoluteTimeRange } from '@grafana/data';
|
|
|
import { advanceTo, clear, advanceBy } from 'jest-date-mock';
|
|
|
import { beforeEach } from 'test/lib/common';
|
|
|
import { DataQueryResponseData } from '@grafana/ui';
|
|
|
@@ -11,8 +12,13 @@ describe('Language completion provider', () => {
|
|
|
metadataRequest: () => ({ data: { data: [] as DataQueryResponseData[] } }),
|
|
|
};
|
|
|
|
|
|
+ const rangeMock: AbsoluteTimeRange = {
|
|
|
+ from: 1560153109000,
|
|
|
+ to: 1560163909000,
|
|
|
+ };
|
|
|
+
|
|
|
describe('empty query suggestions', () => {
|
|
|
- it('returns no suggestions on emtpty context', () => {
|
|
|
+ it('returns no suggestions on empty context', () => {
|
|
|
const instance = new LanguageProvider(datasource);
|
|
|
const value = Plain.deserialize('');
|
|
|
const result = instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] });
|
|
|
@@ -21,7 +27,7 @@ describe('Language completion provider', () => {
|
|
|
expect(result.suggestions.length).toEqual(0);
|
|
|
});
|
|
|
|
|
|
- it('returns default suggestions with history on emtpty context when history was provided', () => {
|
|
|
+ it('returns default suggestions with history on empty context when history was provided', () => {
|
|
|
const instance = new LanguageProvider(datasource);
|
|
|
const value = Plain.deserialize('');
|
|
|
const history = [
|
|
|
@@ -29,7 +35,10 @@ describe('Language completion provider', () => {
|
|
|
query: { refId: '1', expr: '{app="foo"}' },
|
|
|
},
|
|
|
];
|
|
|
- const result = instance.provideCompletionItems({ text: '', prefix: '', value, wrapperClasses: [] }, { history });
|
|
|
+ const result = instance.provideCompletionItems(
|
|
|
+ { text: '', prefix: '', value, wrapperClasses: [] },
|
|
|
+ { history, absoluteRange: rangeMock }
|
|
|
+ );
|
|
|
expect(result.context).toBeUndefined();
|
|
|
expect(result.refresher).toBeUndefined();
|
|
|
expect(result.suggestions).toMatchObject([
|
|
|
@@ -79,64 +88,102 @@ describe('Language completion provider', () => {
|
|
|
anchorOffset: 1,
|
|
|
});
|
|
|
const valueWithSelection = value.change().select(range).value;
|
|
|
- const result = instance.provideCompletionItems({
|
|
|
- text: '',
|
|
|
- prefix: '',
|
|
|
- wrapperClasses: ['context-labels'],
|
|
|
- value: valueWithSelection,
|
|
|
- });
|
|
|
+ const result = instance.provideCompletionItems(
|
|
|
+ {
|
|
|
+ text: '',
|
|
|
+ prefix: '',
|
|
|
+ wrapperClasses: ['context-labels'],
|
|
|
+ value: valueWithSelection,
|
|
|
+ },
|
|
|
+ { absoluteRange: rangeMock }
|
|
|
+ );
|
|
|
expect(result.context).toBe('context-labels');
|
|
|
expect(result.suggestions).toEqual([{ items: [{ label: 'job' }, { label: 'namespace' }], label: 'Labels' }]);
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+describe('Request URL', () => {
|
|
|
+ it('should contain range params', async () => {
|
|
|
+ const rangeMock: AbsoluteTimeRange = {
|
|
|
+ from: 1560153109000,
|
|
|
+ to: 1560163909000,
|
|
|
+ };
|
|
|
+
|
|
|
+ const datasourceWithLabels = {
|
|
|
+ metadataRequest: url => {
|
|
|
+ if (url.slice(0, 15) === '/api/prom/label') {
|
|
|
+ return { data: { data: ['other'] } };
|
|
|
+ } else {
|
|
|
+ return { data: { data: [] } };
|
|
|
+ }
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const datasourceSpy = jest.spyOn(datasourceWithLabels, 'metadataRequest');
|
|
|
+
|
|
|
+ const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
|
|
|
+ await instance.refreshLogLabels(rangeMock, true);
|
|
|
+ const expectedUrl = '/api/prom/label';
|
|
|
+ expect(datasourceSpy).toHaveBeenCalledWith(expectedUrl, rangeToParams(rangeMock));
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
describe('Query imports', () => {
|
|
|
const datasource = {
|
|
|
metadataRequest: () => ({ data: { data: [] as DataQueryResponseData[] } }),
|
|
|
};
|
|
|
|
|
|
+ const rangeMock: AbsoluteTimeRange = {
|
|
|
+ from: 1560153109000,
|
|
|
+ to: 1560163909000,
|
|
|
+ };
|
|
|
+
|
|
|
it('returns empty queries for unknown origin datasource', async () => {
|
|
|
- const instance = new LanguageProvider(datasource);
|
|
|
+ const instance = new LanguageProvider(datasource, { initialRange: rangeMock });
|
|
|
const result = await instance.importQueries([{ refId: 'bar', expr: 'foo' }], 'unknown');
|
|
|
expect(result).toEqual([{ refId: 'bar', expr: '' }]);
|
|
|
});
|
|
|
|
|
|
describe('prometheus query imports', () => {
|
|
|
it('returns empty query from metric-only query', async () => {
|
|
|
- const instance = new LanguageProvider(datasource);
|
|
|
+ const instance = new LanguageProvider(datasource, { initialRange: rangeMock });
|
|
|
const result = await instance.importPrometheusQuery('foo');
|
|
|
expect(result).toEqual('');
|
|
|
});
|
|
|
|
|
|
it('returns empty query from selector query if label is not available', async () => {
|
|
|
const datasourceWithLabels = {
|
|
|
- metadataRequest: (url: string) =>
|
|
|
- url === '/api/prom/label' ? { data: { data: ['other'] } } : { data: { data: [] as DataQueryResponseData[] } },
|
|
|
+ metadataRequest: url =>
|
|
|
+ url.slice(0, 15) === '/api/prom/label'
|
|
|
+ ? { data: { data: ['other'] } }
|
|
|
+ : { data: { data: [] as DataQueryResponseData[] } },
|
|
|
};
|
|
|
- const instance = new LanguageProvider(datasourceWithLabels);
|
|
|
+ const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
|
|
|
const result = await instance.importPrometheusQuery('{foo="bar"}');
|
|
|
expect(result).toEqual('{}');
|
|
|
});
|
|
|
|
|
|
it('returns selector query from selector query with common labels', async () => {
|
|
|
const datasourceWithLabels = {
|
|
|
- metadataRequest: (url: string) =>
|
|
|
- url === '/api/prom/label' ? { data: { data: ['foo'] } } : { data: { data: [] as DataQueryResponseData[] } },
|
|
|
+ metadataRequest: url =>
|
|
|
+ url.slice(0, 15) === '/api/prom/label'
|
|
|
+ ? { data: { data: ['foo'] } }
|
|
|
+ : { data: { data: [] as DataQueryResponseData[] } },
|
|
|
};
|
|
|
- const instance = new LanguageProvider(datasourceWithLabels);
|
|
|
+ const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
|
|
|
const result = await instance.importPrometheusQuery('metric{foo="bar",baz="42"}');
|
|
|
expect(result).toEqual('{foo="bar"}');
|
|
|
});
|
|
|
|
|
|
it('returns selector query from selector query with all labels if logging label list is empty', async () => {
|
|
|
const datasourceWithLabels = {
|
|
|
- metadataRequest: (url: string) =>
|
|
|
- url === '/api/prom/label'
|
|
|
+ metadataRequest: url =>
|
|
|
+ url.slice(0, 15) === '/api/prom/label'
|
|
|
? { data: { data: [] as DataQueryResponseData[] } }
|
|
|
: { data: { data: [] as DataQueryResponseData[] } },
|
|
|
};
|
|
|
- const instance = new LanguageProvider(datasourceWithLabels);
|
|
|
+ const instance = new LanguageProvider(datasourceWithLabels, { initialRange: rangeMock });
|
|
|
const result = await instance.importPrometheusQuery('metric{foo="bar",baz="42"}');
|
|
|
expect(result).toEqual('{baz="42",foo="bar"}');
|
|
|
});
|
|
|
@@ -149,6 +196,11 @@ describe('Labels refresh', () => {
|
|
|
};
|
|
|
const instance = new LanguageProvider(datasource);
|
|
|
|
|
|
+ const rangeMock: AbsoluteTimeRange = {
|
|
|
+ from: 1560153109000,
|
|
|
+ to: 1560163909000,
|
|
|
+ };
|
|
|
+
|
|
|
beforeEach(() => {
|
|
|
instance.fetchLogLabels = jest.fn();
|
|
|
});
|
|
|
@@ -157,18 +209,20 @@ describe('Labels refresh', () => {
|
|
|
jest.clearAllMocks();
|
|
|
clear();
|
|
|
});
|
|
|
+
|
|
|
it("should not refresh labels if refresh interval hasn't passed", () => {
|
|
|
advanceTo(new Date(2019, 1, 1, 0, 0, 0));
|
|
|
instance.logLabelFetchTs = Date.now();
|
|
|
advanceBy(LABEL_REFRESH_INTERVAL / 2);
|
|
|
- instance.refreshLogLabels();
|
|
|
+ instance.refreshLogLabels(rangeMock);
|
|
|
expect(instance.fetchLogLabels).not.toBeCalled();
|
|
|
});
|
|
|
+
|
|
|
it('should refresh labels if refresh interval passed', () => {
|
|
|
advanceTo(new Date(2019, 1, 1, 0, 0, 0));
|
|
|
instance.logLabelFetchTs = Date.now();
|
|
|
advanceBy(LABEL_REFRESH_INTERVAL + 1);
|
|
|
- instance.refreshLogLabels();
|
|
|
+ instance.refreshLogLabels(rangeMock);
|
|
|
expect(instance.fetchLogLabels).toBeCalled();
|
|
|
});
|
|
|
});
|