AzureMonitor: Fix metric namespace clear (#41878) (#41944)

(cherry picked from commit c5241731de)

Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
This commit is contained in:
Grot (@grafanabot) 2021-11-19 04:38:20 -05:00 committed by GitHub
parent ed00b3cf50
commit 0838146d16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 12 deletions

View File

@ -0,0 +1,42 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import MetricNamespaceField from './MetricNamespaceField';
import createMockQuery from '../../__mocks__/query';
import createMockDatasource from '../../__mocks__/datasource';
import { AzureMonitorOption } from '../../types';
const props = {
metricNamespaces: [],
query: createMockQuery(),
datasource: createMockDatasource(),
variableOptionGroup: { label: 'Templates', options: [] },
onQueryChange: jest.fn(),
setError: jest.fn(),
};
describe('Azure Monitor QueryEditor', () => {
it('should render the current value', async () => {
const metricNamespaces: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
const query = {
...props.query,
azureMonitor: {
metricNamespace: 'foo',
},
};
render(<MetricNamespaceField {...props} metricNamespaces={metricNamespaces} query={query} />);
expect(screen.queryByText('foo')).toBeInTheDocument();
});
it('should render the current value even if it is not in the list of options', async () => {
const metricNamespaces: AzureMonitorOption[] = [{ label: 'foo', value: 'foo' }];
const query = {
...props.query,
azureMonitor: {
metricNamespace: 'bar',
},
};
render(<MetricNamespaceField {...props} metricNamespaces={metricNamespaces} query={query} />);
expect(screen.queryByText('bar')).toBeInTheDocument();
expect(screen.queryByText('foo')).not.toBeInTheDocument();
});
});

View File

@ -29,6 +29,11 @@ const MetricNamespaceField: React.FC<MetricNamespaceFieldProps> = ({
);
const options = useMemo(() => [...metricNamespaces, variableOptionGroup], [metricNamespaces, variableOptionGroup]);
const optionValues = metricNamespaces.map((m) => m.value).concat(variableOptionGroup.options.map((p) => p.value));
const value = query.azureMonitor?.metricNamespace;
if (value && !optionValues.includes(value)) {
options.push({ label: value, value });
}
return (
<Field label="Metric namespace">

View File

@ -5,6 +5,7 @@ import {
updateSubscriptions,
useAsyncState,
useMetricNames,
useMetricNamespaces,
useResourceGroups,
useResourceNames,
useResourceTypes,
@ -93,7 +94,7 @@ interface TestScenario {
invalidQueryPartial: AzureMetricQuery;
templateVariableQueryPartial: AzureMetricQuery;
expectedClearedQueryPartial: AzureMetricQuery;
expectedClearedQueryPartial?: AzureMetricQuery;
expectedOptions: AzureMonitorOption[];
}
@ -253,6 +254,47 @@ describe('AzureMonitor: metrics dataHooks', () => {
metricName: undefined,
},
},
{
name: 'useMetricNamespaces',
hook: useMetricNamespaces,
emptyQueryPartial: {
resourceGroup: 'web-app-development',
metricDefinition: 'azure/vm',
resourceName: 'web-server',
metricNamespace: 'azure/vm',
},
validQueryPartial: {
resourceGroup: 'web-app-development',
metricDefinition: 'azure/vm',
resourceName: 'web-server',
metricNamespace: 'azure/vm',
},
invalidQueryPartial: {
resourceGroup: 'web-app-development',
metricDefinition: 'azure/vm',
resourceName: 'web-server',
metricNamespace: 'azure/vm',
metricName: 'invalid-metric',
},
templateVariableQueryPartial: {
resourceGroup: 'web-app-development',
metricDefinition: 'azure/vm',
resourceName: 'web-server',
metricNamespace: 'azure/vm',
metricName: '$variable',
},
expectedOptions: [
{
label: 'Compute Virtual Machine',
value: 'azure/vmc',
},
{
label: 'Database NS',
value: 'azure/dbns',
},
],
},
];
let datasource: MockedObjectDeep<Datasource>;
@ -284,8 +326,11 @@ describe('AzureMonitor: metrics dataHooks', () => {
datasource.getMetricNames = jest
.fn()
.mockResolvedValue([opt('Percentage CPU', 'percentage-cpu'), opt('Free memory', 'free-memory')]);
});
datasource.getMetricNamespaces = jest
.fn()
.mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
});
describe.each(testTable)('scenario %#: $name', (scenario) => {
it('returns values', async () => {
const query = {
@ -339,14 +384,18 @@ describe('AzureMonitor: metrics dataHooks', () => {
const { waitForNextUpdate } = renderHook(() => scenario.hook(query, datasource, onChange, setError));
await waitForNextUpdate(WAIT_OPTIONS);
expect(onChange).toHaveBeenCalledWith({
...query,
azureMonitor: {
...scenario.expectedClearedQueryPartial,
dimensionFilters: [],
timeGrain: '',
},
});
if (scenario.expectedClearedQueryPartial) {
expect(onChange).toHaveBeenCalledWith({
...query,
azureMonitor: {
...scenario.expectedClearedQueryPartial,
dimensionFilters: [],
timeGrain: '',
},
});
} else {
expect(onChange).not.toHaveBeenCalled();
}
});
});
});

View File

@ -193,8 +193,6 @@ export const useMetricNamespaces: DataHook = (query, datasource, onChange, setEr
// Do some cleanup of the query state if need be
if (!metricNamespace && options.length) {
onChange(setMetricNamespace(query, options[0].value));
} else if (options[0] && isInvalidOption(metricNamespace, options, datasource.getVariables())) {
onChange(setMetricNamespace(query, options[0].value));
}
return options;