mirror of
https://github.com/grafana/grafana.git
synced 2024-12-30 10:47:30 -06:00
Alerting: Add validation for path separators in the rule group edit modal (#90887)
Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
This commit is contained in:
parent
c694c97651
commit
746e2eeee6
@ -1,6 +1,4 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import * as React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { render, screen, userEvent } from 'test/test-utils';
|
||||
import { byLabelText, byTestId, byText, byTitle } from 'testing-library-selector';
|
||||
|
||||
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
||||
@ -13,8 +11,6 @@ import {
|
||||
mockPromRecordingRule,
|
||||
mockRulerAlertingRule,
|
||||
mockRulerRecordingRule,
|
||||
mockRulerRuleGroup,
|
||||
mockStore,
|
||||
} from '../../mocks';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
|
||||
@ -31,29 +27,8 @@ const ui = {
|
||||
tableRows: byTestId('row'),
|
||||
noRulesText: byText('This group does not contain alert rules.'),
|
||||
};
|
||||
mockRulerRuleGroup({
|
||||
name: 'group1',
|
||||
rules: [
|
||||
mockRulerRecordingRule({
|
||||
record: 'instance:node_num_cpu:sum',
|
||||
expr: 'count without (cpu) (count without (mode) (node_cpu_seconds_total{job="integrations/node_exporter"}))',
|
||||
labels: { type: 'cpu' },
|
||||
}),
|
||||
mockRulerAlertingRule({ alert: 'nonRecordingRule' }),
|
||||
],
|
||||
});
|
||||
|
||||
jest.mock('app/types', () => ({
|
||||
...jest.requireActual('app/types'),
|
||||
useDispatch: () => jest.fn(),
|
||||
}));
|
||||
|
||||
function getProvidersWrapper() {
|
||||
return function Wrapper({ children }: React.PropsWithChildren<{}>) {
|
||||
const store = mockStore(() => null);
|
||||
return <Provider store={store}>{children}</Provider>;
|
||||
};
|
||||
}
|
||||
const noop = () => jest.fn();
|
||||
|
||||
describe('EditGroupModal', () => {
|
||||
it('Should disable all inputs but interval when intervalEditOnly is set', async () => {
|
||||
@ -65,9 +40,7 @@ describe('EditGroupModal', () => {
|
||||
|
||||
const group = namespace.groups[0];
|
||||
|
||||
render(<EditCloudGroupModal namespace={namespace} group={group} intervalEditOnly onClose={() => jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
render(<EditCloudGroupModal namespace={namespace} group={group} intervalEditOnly onClose={noop} />);
|
||||
|
||||
expect(await ui.input.namespace.find()).toHaveAttribute('readonly');
|
||||
expect(ui.input.group.get()).toHaveAttribute('readonly');
|
||||
@ -107,9 +80,7 @@ describe('EditGroupModal component on cloud alert rules', () => {
|
||||
|
||||
const group = promNs.groups[0];
|
||||
|
||||
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={() => jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={noop} />);
|
||||
|
||||
expect(await ui.input.namespace.find()).toHaveValue('prometheus-ns');
|
||||
expect(ui.input.namespace.get()).not.toHaveAttribute('readonly');
|
||||
@ -128,9 +99,7 @@ describe('EditGroupModal component on cloud alert rules', () => {
|
||||
|
||||
const group = promNs.groups[0];
|
||||
|
||||
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={noop} />);
|
||||
expect(ui.table.query()).not.toBeInTheDocument();
|
||||
expect(await ui.noRulesText.find()).toBeInTheDocument();
|
||||
});
|
||||
@ -163,10 +132,11 @@ describe('EditGroupModal component on grafana-managed alert rules', () => {
|
||||
|
||||
const grafanaGroup1 = grafanaNamespace.groups[0];
|
||||
|
||||
const renderWithGrafanaGroup = () =>
|
||||
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={noop} />);
|
||||
|
||||
it('Should show alert table', async () => {
|
||||
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
renderWithGrafanaGroup();
|
||||
|
||||
expect(await ui.input.namespace.find()).toHaveValue('namespace1');
|
||||
expect(ui.input.group.get()).toHaveValue('grafanaGroup1');
|
||||
@ -178,18 +148,22 @@ describe('EditGroupModal component on grafana-managed alert rules', () => {
|
||||
});
|
||||
|
||||
it('Should have folder input in readonly mode', async () => {
|
||||
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
renderWithGrafanaGroup();
|
||||
|
||||
expect(await ui.input.namespace.find()).toHaveAttribute('readonly');
|
||||
});
|
||||
|
||||
it('Should not display folder link if no folderUrl provided', async () => {
|
||||
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
|
||||
wrapper: getProvidersWrapper(),
|
||||
});
|
||||
renderWithGrafanaGroup();
|
||||
expect(await ui.input.namespace.find()).toHaveValue('namespace1');
|
||||
expect(ui.folderLink.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not allow slashes in the group name', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderWithGrafanaGroup();
|
||||
await user.type(await ui.input.group.find(), 'group/with/slashes');
|
||||
await user.click(ui.input.interval.get());
|
||||
expect(await screen.findByText(/cannot contain \"\/\"/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -28,6 +28,7 @@ import { EvaluationIntervalLimitExceeded } from '../InvalidIntervalWarning';
|
||||
import { decodeGrafanaNamespace, encodeGrafanaNamespace } from '../expressions/util';
|
||||
import { EvaluationGroupQuickPick } from '../rule-editor/EvaluationGroupQuickPick';
|
||||
import { MIN_TIME_RANGE_STEP_S } from '../rule-editor/GrafanaEvaluationBehavior';
|
||||
import { checkForPathSeparator } from '../rule-editor/util';
|
||||
|
||||
const ITEMS_PER_PAGE = 10;
|
||||
|
||||
@ -299,6 +300,11 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement {
|
||||
readOnly={intervalEditOnly || isGrafanaManagedGroup}
|
||||
{...register('namespaceName', {
|
||||
required: 'Namespace name is required.',
|
||||
validate: {
|
||||
// for Grafana-managed we do not validate the name of the folder because we use the UID anyway
|
||||
pathSeparator: (namespaceName) =>
|
||||
isGrafanaManagedGroup ? true : checkForPathSeparator(namespaceName),
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Field>
|
||||
@ -331,6 +337,9 @@ export function EditCloudGroupModal(props: ModalProps): React.ReactElement {
|
||||
readOnly={intervalEditOnly}
|
||||
{...register('groupName', {
|
||||
required: 'Evaluation group name is required.',
|
||||
validate: {
|
||||
pathSeparator: (namespace) => checkForPathSeparator(namespace),
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Field>
|
||||
|
Loading…
Reference in New Issue
Block a user