grafana_bak/public/app/plugins/datasource/loki/languageUtils.test.ts
2025-04-01 10:38:02 +09:00

130 lines
4.4 KiB
TypeScript

import { toDataFrame, FieldType, AbstractQuery, AbstractLabelOperator } from '@grafana/data';
import {
abstractQueryToExpr,
escapeLabelValueInExactSelector,
getLabelTypeFromFrame,
isBytesString,
processLabels,
unescapeLabelValue,
} from './languageUtils';
import { LabelType } from './types';
describe('isBytesString', () => {
it('correctly matches bytes string with integers', () => {
expect(isBytesString('500b')).toBe(true);
expect(isBytesString('2TB')).toBe(true);
});
it('correctly matches bytes string with float', () => {
expect(isBytesString('500.4kib')).toBe(true);
expect(isBytesString('10.4654Mib')).toBe(true);
});
it('does not match integer without unit', () => {
expect(isBytesString('500')).toBe(false);
expect(isBytesString('10')).toBe(false);
});
it('does not match float without unit', () => {
expect(isBytesString('50.047')).toBe(false);
expect(isBytesString('1.234')).toBe(false);
});
});
describe('escapeLabelValueInExactSelector', () => {
it.each`
value | escapedValue
${'nothing to escape'} | ${'nothing to escape'}
${'escape quote: "'} | ${'escape quote: \\"'}
${'escape newline: \nend'} | ${'escape newline: \\nend'}
${'escape slash: \\'} | ${'escape slash: \\\\'}
`('when called with $value', ({ value, escapedValue }) => {
expect(escapeLabelValueInExactSelector(value)).toEqual(escapedValue);
});
});
describe('unescapeLabelValueInExactSelector', () => {
it.each`
value | unescapedValue
${'nothing to unescape'} | ${'nothing to unescape'}
${'escape quote: \\"'} | ${'escape quote: "'}
${'escape newline: \\nend'} | ${'escape newline: \nend'}
${'escape slash: \\\\'} | ${'escape slash: \\'}
`('when called with $value', ({ value, unescapedValue }) => {
expect(unescapeLabelValue(value)).toEqual(unescapedValue);
});
});
describe('getLabelTypeFromFrame', () => {
const frameWithTypes = toDataFrame({
fields: [
{ name: 'Time', type: FieldType.time, values: [0] },
{
name: 'Line',
type: FieldType.string,
values: ['line1'],
},
{ name: 'labelTypes', type: FieldType.other, values: [{ indexed: 'I', parsed: 'P', structured: 'S' }] },
],
});
const frameWithoutTypes = toDataFrame({
fields: [
{ name: 'Time', type: FieldType.time, values: [0] },
{
name: 'Line',
type: FieldType.string,
values: ['line1'],
},
{ name: 'labels', type: FieldType.other, values: [{ job: 'test' }] },
],
});
it('returns structuredMetadata', () => {
expect(getLabelTypeFromFrame('structured', frameWithTypes, 0)).toBe(LabelType.StructuredMetadata);
});
it('returns indexed', () => {
expect(getLabelTypeFromFrame('indexed', frameWithTypes, 0)).toBe(LabelType.Indexed);
});
it('returns parsed', () => {
expect(getLabelTypeFromFrame('parsed', frameWithTypes, 0)).toBe(LabelType.Parsed);
});
it('returns null for unknown field', () => {
expect(getLabelTypeFromFrame('unknown', frameWithTypes, 0)).toBe(null);
});
it('returns null for frame without types', () => {
expect(getLabelTypeFromFrame('job', frameWithoutTypes, 0)).toBe(null);
});
});
describe('abstractQueryToExpr', () => {
it('export abstract query to expr', () => {
const abstractQuery: AbstractQuery = {
refId: 'bar',
labelMatchers: [
{ name: 'label1', operator: AbstractLabelOperator.Equal, value: 'value1' },
{ name: 'label2', operator: AbstractLabelOperator.NotEqual, value: 'value2' },
{ name: 'label3', operator: AbstractLabelOperator.EqualRegEx, value: 'value3' },
{ name: 'label4', operator: AbstractLabelOperator.NotEqualRegEx, value: 'value4' },
],
};
expect(abstractQueryToExpr(abstractQuery)).toBe(
'{label1="value1", label2!="value2", label3=~"value3", label4!~"value4"}'
);
});
});
describe('processLabels', () => {
it('export abstract query to expr', () => {
const labels: Array<{ [key: string]: string }> = [
{ label1: 'value1' },
{ label2: 'value2' },
{ label3: 'value3' },
{ label1: 'value1' },
{ label1: 'value1b' },
];
expect(processLabels(labels)).toEqual({
keys: ['label1', 'label2', 'label3'],
values: { label1: ['value1', 'value1b'], label2: ['value2'], label3: ['value3'] },
});
});
});