CloudWatch: Display dynamic label field in case feature is enabled (#48614)

* move metrics editor related files to a separate folder

* cleanup

* add tests

* remove snapshot test

* nit

* remove unsued import

* remove snapshot
This commit is contained in:
Erik Sundell 2022-05-04 07:36:18 +02:00 committed by GitHub
parent 66d7105b34
commit 0d60b1ce0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 98 additions and 45 deletions

View File

@ -6,9 +6,10 @@ import { Input } from '@grafana/ui';
export interface Props {
onChange: (alias: any) => void;
value: string;
id?: string;
}
export const Alias: FunctionComponent<Props> = ({ value = '', onChange }) => {
export const Alias: FunctionComponent<Props> = ({ value = '', onChange, id }) => {
const [alias, setAlias] = useState(value);
const propagateOnChange = debounce(onChange, 1500);
@ -18,5 +19,5 @@ export const Alias: FunctionComponent<Props> = ({ value = '', onChange }) => {
propagateOnChange(e.target.value);
};
return <Input type="text" value={alias} onChange={onChange} aria-label="Optional alias" />;
return <Input id={id} type="text" value={alias} onChange={onChange} aria-label="Optional alias" />;
};

View File

@ -1,14 +1,14 @@
import { render, screen, act } from '@testing-library/react';
import React from 'react';
import selectEvent from 'react-select-event';
import renderer from 'react-test-renderer';
import { DataSourceInstanceSettings } from '@grafana/data';
import { config } from '@grafana/runtime';
import { TemplateSrv } from 'app/features/templating/template_srv';
import { CustomVariableModel, initialVariableModelState } from '../../../../features/variables/types';
import { CloudWatchDatasource } from '../datasource';
import { CloudWatchJsonData, MetricEditorMode, MetricQueryType } from '../types';
import { CustomVariableModel, initialVariableModelState } from '../../../../../features/variables/types';
import { CloudWatchDatasource } from '../../datasource';
import { CloudWatchJsonData, MetricEditorMode, MetricQueryType } from '../../types';
import { MetricsQueryEditor, Props } from './MetricsQueryEditor';
@ -70,15 +70,6 @@ const setup = () => {
};
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();
});
});
describe('should handle editor modes correctly', () => {
it('when metric query type is metric search and editor mode is builder', async () => {
await act(async () => {
@ -165,4 +156,48 @@ describe('QueryEditor', () => {
expect(await screen.findByText('*')).toBeInTheDocument();
});
});
describe('when dynamic labels feature toggle is enabled', () => {
it('shoud render label field', async () => {
await act(async () => {
const props = setup();
const originalValue = config.featureToggles.cloudWatchDynamicLabels;
config.featureToggles.cloudWatchDynamicLabels = true;
render(
<MetricsQueryEditor
{...props}
query={{ ...props.query, refId: 'A', alias: 'Period: {{period}} InstanceId: {{InstanceId}}' }}
/>
);
expect(screen.getByText('Label')).toBeInTheDocument();
expect(screen.queryByText('Alias')).toBeNull();
expect(screen.getByLabelText('Label - optional')).toHaveValue(
"Period: ${PROP('Period')} InstanceId: ${PROP('Dim.InstanceId')}"
);
config.featureToggles.cloudWatchDynamicLabels = originalValue;
});
});
});
describe('when dynamic labels feature toggle is disabled', () => {
it('shoud render alias field', async () => {
await act(async () => {
const props = setup();
const originalValue = config.featureToggles.cloudWatchDynamicLabels;
config.featureToggles.cloudWatchDynamicLabels = false;
const expected = 'Period: {{period}} InstanceId: {{InstanceId}}';
render(<MetricsQueryEditor {...props} query={{ ...props.query, refId: 'A', alias: expected }} />);
expect(await screen.getByText('Alias')).toBeInTheDocument();
expect(screen.queryByText('Label')).toBeNull();
expect(screen.getByLabelText('Alias - optional')).toHaveValue(expected);
config.featureToggles.cloudWatchDynamicLabels = originalValue;
});
});
});
});

View File

@ -2,10 +2,12 @@ import React, { ChangeEvent, useState } from 'react';
import { QueryEditorProps } from '@grafana/data';
import { EditorField, EditorRow, Space } from '@grafana/experimental';
import { config } from '@grafana/runtime';
import { Input } from '@grafana/ui';
import { CloudWatchDatasource } from '../datasource';
import { isCloudWatchMetricsQuery } from '../guards';
import { MathExpressionQueryField, MetricStatEditor, SQLBuilderEditor, SQLCodeEditor } from '../';
import { CloudWatchDatasource } from '../../datasource';
import { isCloudWatchMetricsQuery } from '../../guards';
import {
CloudWatchJsonData,
CloudWatchMetricsQuery,
@ -13,13 +15,12 @@ import {
MetricEditorMode,
MetricQueryType,
MetricStat,
} from '../types';
} from '../../types';
import QueryHeader from '../QueryHeader';
import QueryHeader from './QueryHeader';
import { Alias } from './Alias';
import usePreparedMetricsQuery from './usePreparedMetricsQuery';
import { Alias, MathExpressionQueryField, MetricStatEditor, SQLBuilderEditor, SQLCodeEditor } from './';
export interface Props extends QueryEditorProps<CloudWatchDatasource, CloudWatchQuery, CloudWatchJsonData> {
query: CloudWatchMetricsQuery;
}
@ -130,17 +131,37 @@ export const MetricsQueryEditor = (props: Props) => {
/>
</EditorField>
<EditorField
label="Alias"
width={26}
optional
tooltip="Change time series legend name using this field. See documentation for replacement variable formats."
>
<Alias
value={preparedQuery.alias ?? ''}
onChange={(value: string) => onChange({ ...preparedQuery, alias: value })}
/>
</EditorField>
{config.featureToggles.cloudWatchDynamicLabels ? (
<EditorField
label="Label"
width={26}
optional
tooltip="Change time series legend name using Dynamic labels. See documentation for details."
>
<Input
id={`${query.refId}-cloudwatch-metric-query-editor-label`}
placeholder="auto"
onBlur={onRunQuery}
value={preparedQuery.label ?? ''}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
onChange({ ...preparedQuery, label: event.target.value })
}
/>
</EditorField>
) : (
<EditorField
label="Alias"
width={26}
optional
tooltip="Change time series legend name using this field. See documentation for replacement variable formats."
>
<Alias
id={`${query.refId}-cloudwatch-metric-query-editor-alias`}
value={preparedQuery.alias ?? ''}
onChange={(value: string) => onChange({ ...preparedQuery, alias: value })}
/>
</EditorField>
)}
</EditorRow>
</>
);

View File

@ -2,8 +2,8 @@ import { render, screen } from '@testing-library/react';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { setupMockedDataSource } from '../__mocks__/CloudWatchDataSource';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../types';
import { setupMockedDataSource } from '../../__mocks__/CloudWatchDataSource';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../types';
import MetricsQueryHeader from './MetricsQueryHeader';

View File

@ -4,8 +4,8 @@ import { SelectableValue } from '@grafana/data';
import { InlineSelect, FlexItem } from '@grafana/experimental';
import { Button, ConfirmModal, RadioButtonGroup } from '@grafana/ui';
import { CloudWatchDatasource } from '../datasource';
import { CloudWatchMetricsQuery, CloudWatchQuery, MetricEditorMode, MetricQueryType } from '../types';
import { CloudWatchDatasource } from '../../datasource';
import { CloudWatchMetricsQuery, CloudWatchQuery, MetricEditorMode, MetricQueryType } from '../../types';
interface MetricsQueryHeaderProps {
query: CloudWatchMetricsQuery;

View File

@ -1,6 +1,6 @@
import { renderHook } from '@testing-library/react-hooks';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../types';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../types';
import usePreparedMetricsQuery, { DEFAULT_QUERY } from './usePreparedMetricsQuery';

View File

@ -1,8 +1,8 @@
import deepEqual from 'fast-deep-equal';
import { useEffect, useMemo } from 'react';
import { migrateMetricQuery } from '../migrations/metricQueryMigrations';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../types';
import { migrateMetricQuery } from '../../migrations/metricQueryMigrations';
import { CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from '../../types';
export const DEFAULT_QUERY: Omit<CloudWatchMetricsQuery, 'refId'> = {
queryMode: 'Metrics',

View File

@ -6,8 +6,8 @@ import { CloudWatchDatasource } from '../datasource';
import { isCloudWatchMetricsQuery } from '../guards';
import { CloudWatchJsonData, CloudWatchQuery } from '../types';
import { MetricsQueryEditor } from '././MetricsQueryEditor/MetricsQueryEditor';
import LogsQueryEditor from './LogsQueryEditor';
import { MetricsQueryEditor } from './MetricsQueryEditor';
export type Props = QueryEditorProps<CloudWatchDatasource, CloudWatchQuery, CloudWatchJsonData>;

View File

@ -8,7 +8,7 @@ import { CloudWatchDatasource } from '../datasource';
import { useRegions } from '../hooks';
import { CloudWatchQuery, CloudWatchQueryMode } from '../types';
import MetricsQueryHeader from './MetricsQueryHeader';
import MetricsQueryHeader from './MetricsQueryEditor/MetricsQueryHeader';
interface QueryHeaderProps {
query: CloudWatchQuery;

View File

@ -1,3 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`QueryEditor should render component 1`] = `null`;

View File

@ -1,6 +1,5 @@
export { Dimensions } from './Dimensions/Dimensions';
export { QueryInlineField, QueryField } from './Forms';
export { Alias } from './Alias';
export { PanelQueryEditor } from './PanelQueryEditor';
export { CloudWatchLogsQueryEditor } from './LogsQueryEditor';
export { MetricStatEditor } from './MetricStatEditor';