Prometheus: Set default query type values in Explore only for new queries (#41263)

* Prometheus: Override query type only for new queries

* Update comment

* Add tests

* Fix test
This commit is contained in:
Ivana Huckova 2021-11-10 16:25:54 +01:00 committed by GitHub
parent ed030f9c21
commit 9e996eaca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 124 deletions

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import { PromExploreExtraFieldProps, PromExploreExtraField } from './PromExploreExtraField'; import { PromExploreExtraFieldProps, PromExploreExtraField, testIds } from './PromExploreExtraField';
const setup = (propOverrides?: PromExploreExtraFieldProps) => { const setup = (propOverrides?: PromExploreExtraFieldProps) => {
const query = { exemplar: false }; const query = { exemplar: false };
@ -23,11 +23,11 @@ const setup = (propOverrides?: PromExploreExtraFieldProps) => {
describe('PromExploreExtraField', () => { describe('PromExploreExtraField', () => {
it('should render step field', () => { it('should render step field', () => {
setup(); setup();
expect(screen.getByTestId('stepField')).toBeInTheDocument(); expect(screen.getByTestId(testIds.stepField)).toBeInTheDocument();
}); });
it('should render query type field', () => { it('should render query type field', () => {
setup(); setup();
expect(screen.getByTestId('queryTypeField')).toBeInTheDocument(); expect(screen.getByTestId(testIds.queryTypeField)).toBeInTheDocument();
}); });
}); });

View File

@ -66,10 +66,10 @@ export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
} }
return ( return (
<div aria-label="Prometheus extra field" className="gf-form-inline"> <div aria-label="Prometheus extra field" className="gf-form-inline" data-testid={testIds.extraFieldEditor}>
{/*Query type field*/} {/*Query type field*/}
<div <div
data-testid="queryTypeField" data-testid={testIds.queryTypeField}
className={cx( className={cx(
'gf-form explore-input-margin', 'gf-form explore-input-margin',
css` css`
@ -82,13 +82,13 @@ export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
<RadioButtonGroup <RadioButtonGroup
options={rangeOptions} options={rangeOptions}
value={query.range === query.instant ? 'both' : query.instant ? 'instant' : 'range'} value={query.range && query.instant ? 'both' : query.instant ? 'instant' : 'range'}
onChange={onQueryTypeChange} onChange={onQueryTypeChange}
/> />
</div> </div>
{/*Step field*/} {/*Step field*/}
<div <div
data-testid="stepField" data-testid={testIds.stepField}
className={cx( className={cx(
'gf-form', 'gf-form',
css` css`
@ -120,3 +120,9 @@ export const PromExploreExtraField: React.FC<PromExploreExtraFieldProps> = memo(
); );
} }
); );
export const testIds = {
extraFieldEditor: 'prom-editor-extra-field',
stepField: 'prom-editor-extra-field-step',
queryTypeField: 'prom-editor-extra-field-query-type',
};

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { render, screen } from '@testing-library/react';
import { act } from 'react-dom/test-utils'; import PromExploreQueryEditor, { testIds } from './PromExploreQueryEditor';
import PromExploreQueryEditor from './PromExploreQueryEditor'; import { testIds as extraFieldTestIds } from './PromExploreExtraField';
import { PrometheusDatasource } from '../datasource'; import { PrometheusDatasource } from '../datasource';
import { PromQuery } from '../types'; import { PromQuery } from '../types';
import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data'; import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
@ -16,18 +16,21 @@ jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
}; };
}); });
const setup = (renderMethod: any, propOverrides?: object) => { const setup = (propOverrides?: object) => {
const datasourceMock: unknown = { const datasourceMock: unknown = {
languageProvider: { languageProvider: {
syntax: () => {}, syntax: () => {},
getLabelKeys: () => [], getLabelKeys: () => [],
metrics: [], metrics: [],
start: () => Promise.resolve([]),
}, },
getInitHints: () => [],
exemplarsAvailable: true,
}; };
const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource; const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource;
const onRunQuery = jest.fn(); const onRunQuery = jest.fn();
const onChange = jest.fn(); const onChange = jest.fn();
const query: PromQuery = { expr: '', refId: 'A', interval: '1s' }; const query: PromQuery = { expr: '', refId: 'A', interval: '1s', exemplar: true };
const range: TimeRange = { const range: TimeRange = {
from: toUtc('2020-01-01', 'YYYY-MM-DD'), from: toUtc('2020-01-01', 'YYYY-MM-DD'),
to: toUtc('2020-01-02', 'YYYY-MM-DD'), to: toUtc('2020-01-02', 'YYYY-MM-DD'),
@ -84,30 +87,55 @@ const setup = (renderMethod: any, propOverrides?: object) => {
Object.assign(props, propOverrides); Object.assign(props, propOverrides);
return renderMethod(<PromExploreQueryEditor {...props} />); return <PromExploreQueryEditor {...props} />;
}; };
describe('PromExploreQueryEditor', () => { describe('PromExploreQueryEditor', () => {
let originalGetSelection: typeof window.getSelection;
beforeAll(() => {
originalGetSelection = window.getSelection;
window.getSelection = () => null;
});
afterAll(() => {
window.getSelection = originalGetSelection;
});
it('should render component', () => { it('should render component', () => {
const wrapper = setup(shallow); render(setup());
expect(wrapper).toMatchSnapshot(); expect(screen.getByTestId(testIds.editor)).toBeInTheDocument();
}); });
it('should render PromQueryField with ExtraFieldElement', async () => { it('should render PromQueryField with ExtraFieldElement', async () => {
// @ts-ignore strict null errpr TS2345: Argument of type '() => Promise<void>' is not assignable to parameter of type '() => void | undefined'. render(setup());
await act(async () => { expect(screen.getByTestId(extraFieldTestIds.extraFieldEditor)).toBeInTheDocument();
const wrapper = setup(shallow); });
expect(wrapper.html()).toContain('aria-label="Prometheus extra field"');
}); it('should set default value for expr if it is undefined', async () => {
const onChange = jest.fn();
const query = { expr: undefined, exemplar: false, instant: false, range: true };
render(setup({ onChange, query }));
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ expr: '' }));
});
it('should set default value for exemplars if it is undefined', async () => {
const onChange = jest.fn();
const query = { expr: '', instant: false, range: true };
render(setup({ onChange, query }));
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ exemplar: true }));
});
it('should set default value for instant and range if expr is falsy', async () => {
const onChange = jest.fn();
let query = { expr: '', exemplar: true };
render(setup({ onChange, query }));
expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ instant: true, range: true }));
});
it('should not set default value for instant and range with truthy expr', async () => {
const onChange = jest.fn();
let query = { expr: 'foo', exemplar: true };
render(setup({ onChange, query }));
expect(onChange).toHaveBeenCalledTimes(0);
});
it('should add default values for multiple missing values', async () => {
const onChange = jest.fn();
let query = {};
render(setup({ onChange, query }));
expect(onChange).toHaveBeenCalledTimes(3);
}); });
}); });

View File

@ -19,7 +19,8 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
onChange({ ...query, exemplar: true }); onChange({ ...query, exemplar: true });
} }
if (!query.instant && !query.range) { // Override query type to "Both" only for new queries (no query.expr).
if (!query.instant && !query.range && !query.expr) {
onChange({ ...query, instant: true, range: true }); onChange({ ...query, instant: true, range: true });
} }
}, [onChange, query]); }, [onChange, query]);
@ -35,6 +36,7 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
onBlur={() => {}} onBlur={() => {}}
history={history} history={history}
data={data} data={data}
data-testid={testIds.editor}
ExtraFieldElement={ ExtraFieldElement={
<PromExploreExtraField query={query} onChange={onChange} datasource={datasource} onRunQuery={onRunQuery} /> <PromExploreExtraField query={query} onChange={onChange} datasource={datasource} onRunQuery={onRunQuery} />
} }
@ -43,3 +45,7 @@ export const PromExploreQueryEditor: FC<Props> = (props: Props) => {
}; };
export default memo(PromExploreQueryEditor); export default memo(PromExploreQueryEditor);
export const testIds = {
editor: 'prom-editor-explore',
};

View File

@ -1,93 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PromExploreQueryEditor should render component 1`] = `
<PromQueryField
ExtraFieldElement={
<Memo
datasource={
Object {
"languageProvider": Object {
"getLabelKeys": [Function],
"metrics": Array [],
"syntax": [Function],
},
}
}
onChange={[MockFunction]}
onRunQuery={[MockFunction]}
query={
Object {
"expr": "",
"interval": "1s",
"refId": "A",
}
}
/>
}
app="explore"
data={
Object {
"request": Object {
"app": "Grafana",
"dashboardId": 1,
"interval": "1s",
"intervalMs": 1000,
"panelId": 1,
"range": Object {
"from": "2020-01-01T00:00:00.000Z",
"raw": Object {
"from": "2020-01-01T00:00:00.000Z",
"to": "2020-01-02T00:00:00.000Z",
},
"to": "2020-01-02T00:00:00.000Z",
},
"requestId": "1",
"scopedVars": Object {},
"startTime": 0,
"targets": Array [],
"timezone": "GMT",
},
"series": Array [],
"state": "NotStarted",
"timeRange": Object {
"from": "2020-01-01T00:00:00.000Z",
"raw": Object {
"from": "2020-01-01T00:00:00.000Z",
"to": "2020-01-02T00:00:00.000Z",
},
"to": "2020-01-02T00:00:00.000Z",
},
}
}
datasource={
Object {
"languageProvider": Object {
"getLabelKeys": [Function],
"metrics": Array [],
"syntax": [Function],
},
}
}
history={Array []}
onBlur={[Function]}
onChange={[MockFunction]}
onRunQuery={[MockFunction]}
query={
Object {
"expr": "",
"interval": "1s",
"refId": "A",
}
}
range={
Object {
"from": "2020-01-01T00:00:00.000Z",
"raw": Object {
"from": "2020-01-01T00:00:00.000Z",
"to": "2020-01-02T00:00:00.000Z",
},
"to": "2020-01-02T00:00:00.000Z",
}
}
/>
`;