mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: add completion unit test
This commit is contained in:
parent
2a5bb57e01
commit
5d3324080a
@ -0,0 +1,290 @@
|
|||||||
|
import { M } from 'msw/lib/glossary-dc3fd077';
|
||||||
|
|
||||||
|
import LokiLanguageProvider from '../../../LanguageProvider';
|
||||||
|
import { LokiDatasource } from '../../../datasource';
|
||||||
|
import { createLokiDatasource } from '../../../mocks';
|
||||||
|
|
||||||
|
import { CompletionDataProvider } from './CompletionDataProvider';
|
||||||
|
import { getCompletions } from './completions';
|
||||||
|
import { Label, Situation } from './situation';
|
||||||
|
|
||||||
|
const history = [
|
||||||
|
{
|
||||||
|
ts: 12345678,
|
||||||
|
query: {
|
||||||
|
refId: 'test-1',
|
||||||
|
expr: '{test: unit}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ts: 87654321,
|
||||||
|
query: {
|
||||||
|
refId: 'test-1',
|
||||||
|
expr: '{test: unit}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const labelNames = ['place', 'source'];
|
||||||
|
const labelValues = ['moon', 'luna'];
|
||||||
|
const extractedLabelKeys = ['extracted', 'label'];
|
||||||
|
const otherLabels: Label[] = [
|
||||||
|
{
|
||||||
|
name: 'place',
|
||||||
|
value: 'luna',
|
||||||
|
op: '=',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const afterSelectorCompletions = [
|
||||||
|
{
|
||||||
|
insertText: '|= "$0"',
|
||||||
|
isSnippet: true,
|
||||||
|
label: '|= "something"',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '!= "$0"',
|
||||||
|
isSnippet: true,
|
||||||
|
label: '!= "something"',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '|~ "$0"',
|
||||||
|
isSnippet: true,
|
||||||
|
label: '|~ "something"',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '!~ "$0"',
|
||||||
|
isSnippet: true,
|
||||||
|
label: '!~ "something"',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '',
|
||||||
|
label: '// Placeholder for the detected parser',
|
||||||
|
type: 'DETECTED_PARSER_PLACEHOLDER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '',
|
||||||
|
label: '// Placeholder for logfmt or json',
|
||||||
|
type: 'OPPOSITE_PARSER_PLACEHOLDER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'pattern',
|
||||||
|
label: 'pattern',
|
||||||
|
type: 'PARSER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'regexp',
|
||||||
|
label: 'regexp',
|
||||||
|
type: 'PARSER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'unpack',
|
||||||
|
label: 'unpack',
|
||||||
|
type: 'PARSER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'unwrap extracted',
|
||||||
|
label: 'unwrap extracted (detected)',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'unwrap label',
|
||||||
|
label: 'unwrap label (detected)',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'unwrap',
|
||||||
|
label: 'unwrap',
|
||||||
|
type: 'LINE_FILTER',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'line_format "{{.$0}}"',
|
||||||
|
isSnippet: true,
|
||||||
|
label: 'line_format',
|
||||||
|
type: 'LINE_FORMAT',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function buildAfterSelectorCompletions(
|
||||||
|
detectedParser: string,
|
||||||
|
detectedParserType: string,
|
||||||
|
otherParser: string,
|
||||||
|
explanation = '(detected)'
|
||||||
|
) {
|
||||||
|
return afterSelectorCompletions.map((completion) => {
|
||||||
|
if (completion.type === 'DETECTED_PARSER_PLACEHOLDER') {
|
||||||
|
return {
|
||||||
|
...completion,
|
||||||
|
type: detectedParserType,
|
||||||
|
label: `${detectedParser} ${explanation}`,
|
||||||
|
insertText: detectedParser,
|
||||||
|
};
|
||||||
|
} else if (completion.type === 'OPPOSITE_PARSER_PLACEHOLDER') {
|
||||||
|
return {
|
||||||
|
...completion,
|
||||||
|
type: 'PARSER',
|
||||||
|
label: otherParser,
|
||||||
|
insertText: otherParser,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...completion };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('getCompletions', () => {
|
||||||
|
let completionProvider: CompletionDataProvider, languageProvider: LokiLanguageProvider, datasource: LokiDatasource;
|
||||||
|
beforeEach(() => {
|
||||||
|
datasource = createLokiDatasource();
|
||||||
|
languageProvider = new LokiLanguageProvider(datasource);
|
||||||
|
completionProvider = new CompletionDataProvider(languageProvider, history);
|
||||||
|
|
||||||
|
jest.spyOn(completionProvider, 'getLabelNames').mockResolvedValue(labelNames);
|
||||||
|
jest.spyOn(completionProvider, 'getLabelValues').mockResolvedValue(labelValues);
|
||||||
|
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
||||||
|
extractedLabelKeys,
|
||||||
|
hasJSON: false,
|
||||||
|
hasLogfmt: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(['EMPTY', 'AT_ROOT'])(`Returns completion options when the situation is %s`, async (type) => {
|
||||||
|
const situation = { type } as Situation;
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toHaveLength(25);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is IN_DURATION', async () => {
|
||||||
|
const situation: Situation = { type: 'IN_DURATION' };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toHaveLength(9);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is IN_GROUPING', async () => {
|
||||||
|
const situation: Situation = { type: 'IN_GROUPING', otherLabels };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toEqual([
|
||||||
|
{
|
||||||
|
insertText: 'place',
|
||||||
|
label: 'place',
|
||||||
|
triggerOnInsert: false,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'source',
|
||||||
|
label: 'source',
|
||||||
|
triggerOnInsert: false,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'extracted',
|
||||||
|
label: 'extracted (parsed)',
|
||||||
|
triggerOnInsert: false,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'label',
|
||||||
|
label: 'label (parsed)',
|
||||||
|
triggerOnInsert: false,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is IN_LABEL_SELECTOR_NO_LABEL_NAME', async () => {
|
||||||
|
const situation: Situation = { type: 'IN_LABEL_SELECTOR_NO_LABEL_NAME', otherLabels };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toEqual([
|
||||||
|
{
|
||||||
|
insertText: 'place=',
|
||||||
|
label: 'place',
|
||||||
|
triggerOnInsert: true,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'source=',
|
||||||
|
label: 'source',
|
||||||
|
triggerOnInsert: true,
|
||||||
|
type: 'LABEL_NAME',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is IN_LABEL_SELECTOR_WITH_LABEL_NAME', async () => {
|
||||||
|
const situation: Situation = {
|
||||||
|
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
|
||||||
|
otherLabels,
|
||||||
|
labelName: '',
|
||||||
|
betweenQuotes: false,
|
||||||
|
};
|
||||||
|
let completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toEqual([
|
||||||
|
{
|
||||||
|
insertText: '"moon"',
|
||||||
|
label: 'moon',
|
||||||
|
type: 'LABEL_VALUE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: '"luna"',
|
||||||
|
label: 'luna',
|
||||||
|
type: 'LABEL_VALUE',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
completions = await getCompletions({ ...situation, betweenQuotes: true }, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toEqual([
|
||||||
|
{
|
||||||
|
insertText: 'moon',
|
||||||
|
label: 'moon',
|
||||||
|
type: 'LABEL_VALUE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
insertText: 'luna',
|
||||||
|
label: 'luna',
|
||||||
|
type: 'LABEL_VALUE',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is AFTER_SELECTOR and JSON parser', async () => {
|
||||||
|
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
||||||
|
extractedLabelKeys,
|
||||||
|
hasJSON: true,
|
||||||
|
hasLogfmt: false,
|
||||||
|
});
|
||||||
|
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe: true };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
const expected = buildAfterSelectorCompletions('json', 'PARSER', 'logfmt');
|
||||||
|
expect(completions).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is AFTER_SELECTOR and Logfmt parser', async () => {
|
||||||
|
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
||||||
|
extractedLabelKeys,
|
||||||
|
hasJSON: false,
|
||||||
|
hasLogfmt: true,
|
||||||
|
});
|
||||||
|
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe: true };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
const expected = buildAfterSelectorCompletions('logfmt', 'DURATION', 'json');
|
||||||
|
expect(completions).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Returns completion options when the situation is IN_AGGREGATION', async () => {
|
||||||
|
const situation: Situation = { type: 'IN_AGGREGATION' };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
|
expect(completions).toHaveLength(22);
|
||||||
|
});
|
||||||
|
});
|
@ -214,15 +214,12 @@ export async function getCompletions(
|
|||||||
dataProvider: CompletionDataProvider
|
dataProvider: CompletionDataProvider
|
||||||
): Promise<Completion[]> {
|
): Promise<Completion[]> {
|
||||||
switch (situation.type) {
|
switch (situation.type) {
|
||||||
|
case 'EMPTY':
|
||||||
case 'AT_ROOT':
|
case 'AT_ROOT':
|
||||||
const historyCompletions = await getAllHistoryCompletions(dataProvider);
|
const historyCompletions = await getAllHistoryCompletions(dataProvider);
|
||||||
return [...historyCompletions, ...LOG_COMPLETIONS, ...AGGREGATION_COMPLETIONS, ...FUNCTION_COMPLETIONS];
|
return [...historyCompletions, ...LOG_COMPLETIONS, ...AGGREGATION_COMPLETIONS, ...FUNCTION_COMPLETIONS];
|
||||||
case 'IN_DURATION':
|
case 'IN_DURATION':
|
||||||
return DURATION_COMPLETIONS;
|
return DURATION_COMPLETIONS;
|
||||||
case 'EMPTY': {
|
|
||||||
const historyCompletions = await getAllHistoryCompletions(dataProvider);
|
|
||||||
return [...historyCompletions, ...LOG_COMPLETIONS, ...AGGREGATION_COMPLETIONS, ...FUNCTION_COMPLETIONS];
|
|
||||||
}
|
|
||||||
case 'IN_GROUPING':
|
case 'IN_GROUPING':
|
||||||
return getInGroupingCompletions(situation.otherLabels, dataProvider);
|
return getInGroupingCompletions(situation.otherLabels, dataProvider);
|
||||||
case 'IN_LABEL_SELECTOR_NO_LABEL_NAME':
|
case 'IN_LABEL_SELECTOR_NO_LABEL_NAME':
|
||||||
|
Loading…
Reference in New Issue
Block a user