mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
* add support for code editor and builder * refactor cloudwatch migration * Add tooltip to editor field (#56) * add tooltip * add old tooltips * Bug bash feedback fixes (#58) * make ASC the default option * update sql preview whenever sql changes * don't allow queries without aggregation * set default value for aggregation * use new input field * cleanup * pr feedback * prevent unnecessary rerenders * use frame error instead of main error * remove not used snapshot * Use dimension filter in schema picker (#63) * use dimension key filter in group by and schema labels * add dimension filter also to code editor * add tests * fix build error * fix strict error * remove debug code * fix annotation editor (#64) * fix annotation editor * fix broken test * revert annotation backend change * PR feedback (#67) * pr feedback * removed dimension filter from group by * add spacing between common fields and rest * do not generate deep link for metric queries (#70) * update docs (#69) Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> * fix lint problem caused by merge conflict Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
216 lines
7.6 KiB
TypeScript
216 lines
7.6 KiB
TypeScript
import React from 'react';
|
|
import renderer from 'react-test-renderer';
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|
import { act } from 'react-dom/test-utils';
|
|
import { DataSourceInstanceSettings } from '@grafana/data';
|
|
import { TemplateSrv } from 'app/features/templating/template_srv';
|
|
import { MetricsQueryEditor, normalizeQuery, Props } from './MetricsQueryEditor';
|
|
import { CloudWatchDatasource } from '../datasource';
|
|
import { CustomVariableModel, initialVariableModelState } from '../../../../features/variables/types';
|
|
import { CloudWatchJsonData, CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../types';
|
|
|
|
const setup = () => {
|
|
const instanceSettings = {
|
|
jsonData: { defaultRegion: 'us-east-1' },
|
|
} as DataSourceInstanceSettings<CloudWatchJsonData>;
|
|
|
|
const templateSrv = new TemplateSrv();
|
|
const variable: CustomVariableModel = {
|
|
...initialVariableModelState,
|
|
id: 'var3',
|
|
index: 0,
|
|
name: 'var3',
|
|
options: [
|
|
{ selected: true, value: 'var3-foo', text: 'var3-foo' },
|
|
{ selected: false, value: 'var3-bar', text: 'var3-bar' },
|
|
{ selected: true, value: 'var3-baz', text: 'var3-baz' },
|
|
],
|
|
current: { selected: true, value: ['var3-foo', 'var3-baz'], text: 'var3-foo + var3-baz' },
|
|
multi: true,
|
|
includeAll: false,
|
|
query: '',
|
|
type: 'custom',
|
|
};
|
|
templateSrv.init([variable]);
|
|
|
|
const datasource = new CloudWatchDatasource(instanceSettings, templateSrv as any, {} as any);
|
|
datasource.metricFindQuery = async () => [{ value: 'test', label: 'test', text: 'test' }];
|
|
datasource.getNamespaces = jest.fn().mockResolvedValue([]);
|
|
datasource.getMetrics = jest.fn().mockResolvedValue([]);
|
|
datasource.getRegions = jest.fn().mockResolvedValue([]);
|
|
datasource.getDimensionKeys = jest.fn().mockResolvedValue([]);
|
|
|
|
const props: Props = {
|
|
query: {
|
|
queryMode: 'Metrics',
|
|
refId: '',
|
|
id: '',
|
|
region: 'us-east-1',
|
|
namespace: 'ec2',
|
|
metricName: 'CPUUtilization',
|
|
dimensions: { somekey: 'somevalue' },
|
|
statistic: '',
|
|
period: '',
|
|
expression: '',
|
|
alias: '',
|
|
matchExact: true,
|
|
metricQueryType: MetricQueryType.Search,
|
|
metricEditorMode: MetricEditorMode.Builder,
|
|
},
|
|
datasource,
|
|
history: [],
|
|
onChange: jest.fn(),
|
|
onRunQuery: jest.fn(),
|
|
};
|
|
|
|
return props;
|
|
};
|
|
|
|
describe('QueryEditor', () => {
|
|
it('should render component', async () => {
|
|
const { act } = renderer;
|
|
await act(async () => {
|
|
const props = setup();
|
|
const tree = renderer.create(<MetricsQueryEditor {...props} />).toJSON();
|
|
expect(tree).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
it('normalizes query on mount', async () => {
|
|
const { act } = renderer;
|
|
const props = setup();
|
|
// This does not actually even conform to the prop type but this happens on initialisation somehow
|
|
props.query = {
|
|
queryMode: 'Metrics',
|
|
apiMode: 'Metrics',
|
|
refId: '',
|
|
expression: '',
|
|
matchExact: true,
|
|
metricQueryType: MetricQueryType.Search,
|
|
metricEditorMode: MetricEditorMode.Builder,
|
|
} as any;
|
|
await act(async () => {
|
|
renderer.create(<MetricsQueryEditor {...props} />);
|
|
});
|
|
expect((props.onChange as jest.Mock).mock.calls[0][0]).toEqual({
|
|
namespace: '',
|
|
metricName: '',
|
|
expression: '',
|
|
sqlExpression: '',
|
|
dimensions: {},
|
|
region: 'default',
|
|
id: '',
|
|
alias: '',
|
|
statistic: 'Average',
|
|
period: '',
|
|
queryMode: 'Metrics',
|
|
apiMode: 'Metrics',
|
|
refId: '',
|
|
matchExact: true,
|
|
metricQueryType: MetricQueryType.Search,
|
|
metricEditorMode: MetricEditorMode.Builder,
|
|
});
|
|
});
|
|
|
|
describe('should use correct default values', () => {
|
|
it('should normalize query with default values', () => {
|
|
expect(normalizeQuery({ refId: '42' } as any)).toEqual({
|
|
namespace: '',
|
|
metricName: '',
|
|
expression: '',
|
|
sqlExpression: '',
|
|
dimensions: {},
|
|
region: 'default',
|
|
id: '',
|
|
alias: '',
|
|
statistic: 'Average',
|
|
matchExact: true,
|
|
period: '',
|
|
queryMode: 'Metrics',
|
|
refId: '42',
|
|
metricQueryType: MetricQueryType.Search,
|
|
metricEditorMode: MetricEditorMode.Builder,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('should handle editor modes correctly', () => {
|
|
it('when metric query type is metric search and editor mode is builder', async () => {
|
|
await act(async () => {
|
|
const props = setup();
|
|
render(<MetricsQueryEditor {...props} />);
|
|
|
|
expect(screen.getByText('Metric Search')).toBeInTheDocument();
|
|
const radio = screen.getByLabelText('Builder');
|
|
expect(radio instanceof HTMLInputElement && radio.checked).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
it('when metric query type is metric search and editor mode is raw', async () => {
|
|
await act(async () => {
|
|
const props = setup();
|
|
(props.query as CloudWatchMetricsQuery).metricEditorMode = MetricEditorMode.Code;
|
|
render(<MetricsQueryEditor {...props} />);
|
|
|
|
expect(screen.getByText('Metric Search')).toBeInTheDocument();
|
|
const radio = screen.getByLabelText('Code');
|
|
expect(radio instanceof HTMLInputElement && radio.checked).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
it('when metric query type is metric query and editor mode is builder', async () => {
|
|
await act(async () => {
|
|
const props = setup();
|
|
(props.query as CloudWatchMetricsQuery).metricQueryType = MetricQueryType.Query;
|
|
(props.query as CloudWatchMetricsQuery).metricEditorMode = MetricEditorMode.Builder;
|
|
render(<MetricsQueryEditor {...props} />);
|
|
|
|
expect(screen.getByText('Metric Query')).toBeInTheDocument();
|
|
const radio = screen.getByLabelText('Builder');
|
|
expect(radio instanceof HTMLInputElement && radio.checked).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
it('when metric query type is metric query and editor mode is raw', async () => {
|
|
await act(async () => {
|
|
const props = setup();
|
|
(props.query as CloudWatchMetricsQuery).metricQueryType = MetricQueryType.Query;
|
|
(props.query as CloudWatchMetricsQuery).metricEditorMode = MetricEditorMode.Code;
|
|
render(<MetricsQueryEditor {...props} />);
|
|
|
|
expect(screen.getByText('Metric Query')).toBeInTheDocument();
|
|
const radio = screen.getByLabelText('Code');
|
|
expect(radio instanceof HTMLInputElement && radio.checked).toBeTruthy();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('should handle expression options correctly', () => {
|
|
it('should display match exact switch', () => {
|
|
const props = setup();
|
|
render(<MetricsQueryEditor {...props} />);
|
|
expect(screen.getByText('Match exact')).toBeInTheDocument();
|
|
});
|
|
|
|
it('shoud display wildcard option in dimension value dropdown', async () => {
|
|
const props = setup();
|
|
props.datasource.getDimensionValues = jest.fn().mockResolvedValue([[{ label: 'dimVal1', value: 'dimVal1' }]]);
|
|
(props.query as CloudWatchMetricsQuery).metricQueryType = MetricQueryType.Search;
|
|
(props.query as CloudWatchMetricsQuery).metricEditorMode = MetricEditorMode.Builder;
|
|
(props.query as CloudWatchMetricsQuery).dimensions = { instanceId: 'instance-123' };
|
|
render(<MetricsQueryEditor {...props} />);
|
|
expect(screen.getByText('Match exact')).toBeInTheDocument();
|
|
|
|
const valueElement = screen.getByText('instance-123');
|
|
expect(valueElement).toBeInTheDocument();
|
|
expect(screen.queryByText('*')).toBeNull();
|
|
act(async () => {
|
|
await valueElement.click();
|
|
await waitFor(() => {
|
|
expect(screen.getByText('*')).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|