diff --git a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.test.tsx index a5f5414da48..ae31f7b755b 100644 --- a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.test.tsx @@ -149,7 +149,7 @@ describe('VariableEditor', () => { // change filter key const keySelect = screen.getByRole('combobox', { name: 'Dimensions filter key' }); // confirms getDimensionKeys was called with filter and that the element uses keysForDimensionFilter - await select(keySelect, 'v4', { + select(keySelect, 'v4', { container: document.body, }); expect(ds.datasource.resources.getDimensionKeys).toHaveBeenCalledWith({ @@ -158,14 +158,16 @@ describe('VariableEditor', () => { metricName: 'i3', dimensionFilters: undefined, }); - expect(onChange).toHaveBeenCalledWith({ - ...defaultQuery, - queryType: VariableQueryType.DimensionValues, - namespace: 'z2', - region: 'a1', - metricName: 'i3', - dimensionKey: 's4', - dimensionFilters: { v4: undefined }, + await waitFor(() => { + expect(onChange).toHaveBeenCalledWith({ + ...defaultQuery, + queryType: VariableQueryType.DimensionValues, + namespace: 'z2', + region: 'a1', + metricName: 'i3', + dimensionKey: 's4', + dimensionFilters: { v4: undefined }, + }); }); // set filter value diff --git a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx index a0f6b550306..262b57c9a77 100644 --- a/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/VariableQueryEditor/VariableQueryEditor.tsx @@ -37,12 +37,11 @@ const queryTypes: Array<{ value: string; label: string }> = [ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => { const parsedQuery = migrateVariableQuery(query); - const { region, namespace, metricName, dimensionKey, dimensionFilters } = parsedQuery; + const { region, namespace, metricName, dimensionKey } = parsedQuery; const [regions, regionIsLoading] = useRegions(datasource); const namespaces = useNamespaces(datasource); const metrics = useMetrics(datasource, { region, namespace }); const dimensionKeys = useDimensionKeys(datasource, { region, namespace, metricName }); - const keysForDimensionFilter = useDimensionKeys(datasource, { region, namespace, metricName, dimensionFilters }); const accountState = useAccountOptions(datasource.resources, query.region); const newFormStylingEnabled = config.featureToggles.awsDatasourcesNewFormStyling; @@ -188,7 +187,6 @@ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => { onChange={(dimensions) => { onChange({ ...parsedQuery, dimensionFilters: dimensions }); }} - dimensionKeys={keysForDimensionFilter} disableExpressions={true} datasource={datasource} /> @@ -205,7 +203,6 @@ export const VariableQueryEditor = ({ query, datasource, onChange }: Props) => { onChange={(dimensions) => { onChange({ ...parsedQuery, dimensionFilters: dimensions }); }} - dimensionKeys={keysForDimensionFilter} disableExpressions={true} datasource={datasource} /> diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx index d0b545a63c2..846d7209a58 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.test.tsx @@ -43,8 +43,8 @@ describe('Dimensions', () => { InstanceId: '*', InstanceGroup: 'Group1', }; - render(); - const filterItems = screen.getAllByTestId('cloudwatch-dimensions-filter-item'); + render(); + const filterItems = await screen.findAllByTestId('cloudwatch-dimensions-filter-item'); expect(filterItems.length).toBe(2); expect(within(filterItems[0]).getByText('InstanceId')).toBeInTheDocument(); @@ -61,8 +61,8 @@ describe('Dimensions', () => { InstanceId: ['*'], InstanceGroup: ['Group1'], }; - render(); - const filterItems = screen.getAllByTestId('cloudwatch-dimensions-filter-item'); + render(); + const filterItems = await screen.findAllByTestId('cloudwatch-dimensions-filter-item'); expect(filterItems.length).toBe(2); expect(within(filterItems[0]).getByText('InstanceId')).toBeInTheDocument(); @@ -77,7 +77,7 @@ describe('Dimensions', () => { it('it should add the new item but not call onChange', async () => { props.query.dimensions = {}; const onChange = jest.fn(); - render(); + render(); await userEvent.click(screen.getByLabelText('Add')); expect(screen.getByTestId('cloudwatch-dimensions-filter-item')).toBeInTheDocument(); @@ -89,9 +89,7 @@ describe('Dimensions', () => { it('it should add the new item but not call onChange', async () => { props.query.dimensions = {}; const onChange = jest.fn(); - const { container } = render( - - ); + const { container } = render(); await userEvent.click(screen.getByLabelText('Add')); const filterItemElement = screen.getByTestId('cloudwatch-dimensions-filter-item'); @@ -109,9 +107,7 @@ describe('Dimensions', () => { it('it should add the new item and trigger onChange', async () => { props.query.dimensions = {}; const onChange = jest.fn(); - const { container } = render( - - ); + const { container } = render(); const label = await screen.findByLabelText('Add'); await userEvent.click(label); @@ -128,11 +124,8 @@ describe('Dimensions', () => { expect(valueElement).toBeInTheDocument(); await userEvent.type(valueElement!, 'my-value'); fireEvent.keyDown(valueElement!, { keyCode: 13 }); - expect(onChange).not.toHaveBeenCalledWith({ - ...props.query, - dimensions: { - 'my-key': 'my-value', - }, + expect(onChange).toHaveBeenCalledWith({ + 'my-key': 'my-value', }); }); }); diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx index 9ca9b1cbc27..3909df54d84 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/Dimensions.tsx @@ -1,7 +1,6 @@ import { isEqual } from 'lodash'; import React, { useMemo, useState } from 'react'; -import { SelectableValue } from '@grafana/data'; import { EditorList } from '@grafana/experimental'; import { CloudWatchDatasource } from '../../../datasource'; @@ -13,7 +12,6 @@ export interface Props { metricStat: MetricStat; onChange: (dimensions: DimensionsType) => void; datasource: CloudWatchDatasource; - dimensionKeys: Array>; disableExpressions: boolean; } @@ -62,7 +60,7 @@ const filterConditionsToDimensions = (filters: DimensionFilterCondition[]) => { }, {}); }; -export const Dimensions = ({ metricStat, datasource, dimensionKeys, disableExpressions, onChange }: Props) => { +export const Dimensions = ({ metricStat, datasource, disableExpressions, onChange }: Props) => { const dimensionFilters = useMemo(() => dimensionsToFilterConditions(metricStat.dimensions), [metricStat.dimensions]); const [items, setItems] = useState(dimensionFilters); const onDimensionsChange = (newItems: Array>) => { @@ -80,17 +78,12 @@ export const Dimensions = ({ metricStat, datasource, dimensionKeys, disableExpre ); }; -function makeRenderFilter( - datasource: CloudWatchDatasource, - metricStat: MetricStat, - dimensionKeys: Array>, - disableExpressions: boolean -) { +function makeRenderFilter(datasource: CloudWatchDatasource, metricStat: MetricStat, disableExpressions: boolean) { function renderFilter( item: DimensionFilterCondition, onChange: (item: DimensionFilterCondition) => void, @@ -103,7 +96,6 @@ function makeRenderFilter( datasource={datasource} metricStat={metricStat} disableExpressions={disableExpressions} - dimensionKeys={dimensionKeys} onDelete={onDelete} /> ); diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx new file mode 100644 index 00000000000..64c658249c2 --- /dev/null +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.test.tsx @@ -0,0 +1,53 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { setupMockedDataSource } from '../../../__mocks__/CloudWatchDataSource'; +import { CloudWatchMetricsQuery } from '../../../types'; + +import { FilterItem } from './FilterItem'; + +const ds = setupMockedDataSource({ + variables: [], +}); + +const q: CloudWatchMetricsQuery = { + id: '', + region: 'us-east-2', + namespace: '', + period: '', + alias: '', + metricName: '', + dimensions: { foo: 'bar', abc: 'xyz' }, + matchExact: true, + statistic: '', + expression: '', + refId: '', +}; + +describe('Dimensions', () => { + it('should call getDimensionKeys without the current key', async () => { + const getDimensionKeys = jest.fn().mockResolvedValue([]); + ds.datasource.resources.getDimensionKeys = getDimensionKeys; + const currFilter = { key: 'foo', value: 'bar' }; + + render( + + ); + await userEvent.click(screen.getByLabelText('Dimensions filter key')); + expect(getDimensionKeys).toHaveBeenCalledWith({ + namespace: q.namespace, + region: q.region, + metricName: q.metricName, + accountId: q.accountId, + dimensionFilters: { abc: ['xyz'] }, + }); + }); +}); diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx index 0d89a68fa9f..7c5e65064c3 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/Dimensions/FilterItem.tsx @@ -7,6 +7,7 @@ import { AccessoryButton, InputGroup } from '@grafana/experimental'; import { Select, useStyles2 } from '@grafana/ui'; import { CloudWatchDatasource } from '../../../datasource'; +import { useDimensionKeys } from '../../../hooks'; import { Dimensions, MetricStat } from '../../../types'; import { appendTemplateVariables } from '../../../utils/utils'; @@ -16,7 +17,6 @@ export interface Props { metricStat: MetricStat; datasource: CloudWatchDatasource; filter: DimensionFilterCondition; - dimensionKeys: Array>; disableExpressions: boolean; onChange: (value: DimensionFilterCondition) => void; onDelete: () => void; @@ -32,19 +32,16 @@ const excludeCurrentKey = (dimensions: Dimensions, currentKey: string | undefine return acc; }, {}); -export const FilterItem = ({ - filter, - metricStat: { region, namespace, metricName, dimensions, accountId }, - datasource, - dimensionKeys, - disableExpressions, - onChange, - onDelete, -}: Props) => { +export const FilterItem = ({ filter, metricStat, datasource, disableExpressions, onChange, onDelete }: Props) => { + const { region, namespace, metricName, dimensions, accountId } = metricStat; const dimensionsExcludingCurrentKey = useMemo( () => excludeCurrentKey(dimensions ?? {}, filter.key), [dimensions, filter] ); + const dimensionKeys = useDimensionKeys(datasource, { + ...metricStat, + dimensionFilters: dimensionsExcludingCurrentKey, + }); const loadDimensionValues = async () => { if (!filter.key) { diff --git a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx index bb57b58a872..1bd3035726a 100644 --- a/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/shared/MetricStatEditor/MetricStatEditor.tsx @@ -6,7 +6,7 @@ import { config } from '@grafana/runtime'; import { Select } from '@grafana/ui'; import { CloudWatchDatasource } from '../../../datasource'; -import { useAccountOptions, useDimensionKeys, useMetrics, useNamespaces } from '../../../hooks'; +import { useAccountOptions, useMetrics, useNamespaces } from '../../../hooks'; import { standardStatistics } from '../../../standardStatistics'; import { MetricStat } from '../../../types'; import { appendTemplateVariables, toOption } from '../../../utils/utils'; @@ -35,7 +35,6 @@ export const MetricStatEditor = ({ }: React.PropsWithChildren) => { const namespaces = useNamespaces(datasource); const metrics = useMetrics(datasource, metricStat); - const dimensionKeys = useDimensionKeys(datasource, { ...metricStat, dimensionFilters: metricStat.dimensions }); const accountState = useAccountOptions(datasource.resources, metricStat.region); useEffect(() => { @@ -139,7 +138,6 @@ export const MetricStatEditor = ({ onChange({ ...metricStat, dimensions })} - dimensionKeys={dimensionKeys} disableExpressions={disableExpressions} datasource={datasource} />