Loki: Pass time range variable in variable editor (#82900)

* Loki: Pass time range variable in variable editor

* Remove not needed type

* Update

* Add tests, not re-run if type does not change

* Add range as dependency
This commit is contained in:
Ivana Huckova 2024-02-20 10:07:42 +01:00 committed by GitHub
parent 6db2d1a411
commit dc718a7d9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 136 additions and 10 deletions

View File

@ -1028,12 +1028,6 @@
"count": 5
}
],
"/packages/grafana-ui/src/components/Splitter/Splitter.tsx": [
{
"message": "Do not use any type assertions.",
"count": 1
}
],
"/packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx": [
{
"message": "Unexpected any. Specify a different type.",

View File

@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { select } from 'react-select-event';
import { TimeRange, dateTime } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { createLokiDatasource } from '../__mocks__/datasource';
@ -133,4 +134,132 @@ describe('LokiVariableQueryEditor', () => {
await select(screen.getByLabelText('Label'), 'luna', { container: document.body });
await screen.findByText('luna');
});
test('Calls language provider fetchLabels with the time range received in props', async () => {
const now = dateTime('2023-09-16T21:26:00Z');
const range: TimeRange = {
from: dateTime(now).subtract(2, 'days'),
to: now,
raw: {
from: 'now-2d',
to: 'now',
},
};
props.range = range;
props.query = {
refId: 'test',
type: LokiVariableQueryType.LabelValues,
label: 'luna',
};
render(<LokiVariableQueryEditor {...props} />);
await waitFor(() =>
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledWith({ timeRange: range })
);
});
test('does not re-run fetch labels when type does not change', async () => {
const now = dateTime('2023-09-16T21:26:00Z');
const range: TimeRange = {
from: dateTime(now).subtract(2, 'days'),
to: now,
raw: {
from: 'now-2d',
to: 'now',
},
};
props.range = range;
props.query = {
refId: 'test',
type: LokiVariableQueryType.LabelValues,
};
props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
const { rerender } = render(<LokiVariableQueryEditor {...props} />);
rerender(
<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelValues }} />
);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
});
});
test('runs fetch labels when type changes to from LabelNames to LabelValues', async () => {
const now = dateTime('2023-09-16T21:26:00Z');
const range: TimeRange = {
from: dateTime(now).subtract(2, 'days'),
to: now,
raw: {
from: 'now-2d',
to: 'now',
},
};
props.range = range;
props.query = {
refId: 'test',
type: LokiVariableQueryType.LabelNames,
};
props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
const { rerender } = render(<LokiVariableQueryEditor {...props} />);
rerender(
<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelValues }} />
);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
});
});
test('runs fetch labels when type changes to LabelValues', async () => {
const now = dateTime('2023-09-16T21:26:00Z');
const range: TimeRange = {
from: dateTime(now).subtract(2, 'days'),
to: now,
raw: {
from: 'now-2d',
to: 'now',
},
};
props.range = range;
props.query = {
refId: 'test',
type: LokiVariableQueryType.LabelNames,
};
props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
// Starting with LabelNames
const { rerender } = render(<LokiVariableQueryEditor {...props} />);
// Changing to LabelValues, should run fetchLabels
rerender(
<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelValues }} />
);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
});
// Keeping the type of LabelValues, should not run additional fetchLabels
rerender(
<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelValues }} />
);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
});
// Changing to LabelNames, should not run additional fetchLabels
rerender(<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelNames }} />);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
});
// Changing to LabelValues, should run additional fetchLabels
rerender(
<LokiVariableQueryEditor {...props} query={{ ...props.query, type: LokiVariableQueryType.LabelValues }} />
);
await waitFor(() => {
expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(2);
});
});
});

View File

@ -1,4 +1,5 @@
import React, { FormEvent, useState, useEffect } from 'react';
import { usePrevious } from 'react-use';
import { QueryEditorProps, SelectableValue } from '@grafana/data';
import { InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
@ -16,11 +17,12 @@ export type Props = QueryEditorProps<LokiDatasource, LokiQuery, LokiOptions, Lok
const refId = 'LokiVariableQueryEditor-VariableQuery';
export const LokiVariableQueryEditor = ({ onChange, query, datasource }: Props) => {
export const LokiVariableQueryEditor = ({ onChange, query, datasource, range }: Props) => {
const [type, setType] = useState<number | undefined>(undefined);
const [label, setLabel] = useState('');
const [labelOptions, setLabelOptions] = useState<Array<SelectableValue<string>>>([]);
const [stream, setStream] = useState('');
const previousType = usePrevious(type);
useEffect(() => {
if (!query) {
@ -34,14 +36,15 @@ export const LokiVariableQueryEditor = ({ onChange, query, datasource }: Props)
}, [query]);
useEffect(() => {
if (type !== QueryType.LabelValues) {
// Fetch label names when the query type is LabelValues, and the previous type was not the same
if (type !== QueryType.LabelValues || previousType === type) {
return;
}
datasource.languageProvider.fetchLabels().then((labelNames: string[]) => {
datasource.languageProvider.fetchLabels({ timeRange: range }).then((labelNames) => {
setLabelOptions(labelNames.map((labelName) => ({ label: labelName, value: labelName })));
});
}, [datasource, type]);
}, [datasource, type, range, previousType]);
const onQueryTypeChange = (newType: SelectableValue<QueryType>) => {
setType(newType.value);