Alerting: Display error if repeat interval is lower than group interval (#69413)
* Display error if repeat interval is lower than group interval * Small change * Update tests
This commit is contained in:
+26
@@ -78,6 +78,32 @@ describe('EditDefaultPolicyForm', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show an error if repeat interval is lower than group interval', async function () {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
|
||||||
|
const onSubmit = jest.fn();
|
||||||
|
renderRouteForm(
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
receiver: 'default',
|
||||||
|
},
|
||||||
|
[{ value: 'default', label: 'Default' }],
|
||||||
|
onSubmit
|
||||||
|
);
|
||||||
|
|
||||||
|
await user.click(ui.timingOptionsBtn.get());
|
||||||
|
|
||||||
|
await user.type(ui.groupWaitInput.get(), '5m25s');
|
||||||
|
await user.type(ui.groupIntervalInput.get(), '35m40s');
|
||||||
|
await user.type(ui.repeatIntervalInput.get(), '30m');
|
||||||
|
|
||||||
|
await user.click(ui.submitBtn.get());
|
||||||
|
|
||||||
|
expect(ui.error.getAll()).toHaveLength(1);
|
||||||
|
expect(ui.error.get().textContent).toBe('Repeat interval should be higher or equal to Group interval');
|
||||||
|
expect(onSubmit).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow resetting existing timing options', async function () {
|
it('should allow resetting existing timing options', async function () {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -10,6 +10,7 @@ import {
|
|||||||
mapMultiSelectValueToStrings,
|
mapMultiSelectValueToStrings,
|
||||||
mapSelectValueToString,
|
mapSelectValueToString,
|
||||||
promDurationValidator,
|
promDurationValidator,
|
||||||
|
repeatIntervalValidator,
|
||||||
stringsToSelectableValues,
|
stringsToSelectableValues,
|
||||||
stringToSelectableValue,
|
stringToSelectableValue,
|
||||||
} from '../../utils/amroutes';
|
} from '../../utils/amroutes';
|
||||||
@@ -43,7 +44,7 @@ export const AmRootRouteForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Form defaultValues={{ ...defaultValues, overrideTimings: true, overrideGrouping: true }} onSubmit={onSubmit}>
|
<Form defaultValues={{ ...defaultValues, overrideTimings: true, overrideGrouping: true }} onSubmit={onSubmit}>
|
||||||
{({ register, control, errors, setValue }) => (
|
{({ register, control, errors, setValue, getValues }) => (
|
||||||
<>
|
<>
|
||||||
<Field label="Default contact point" invalid={!!errors.receiver} error={errors.receiver?.message}>
|
<Field label="Default contact point" invalid={!!errors.receiver} error={errors.receiver?.message}>
|
||||||
<>
|
<>
|
||||||
@@ -143,7 +144,12 @@ export const AmRootRouteForm = ({
|
|||||||
data-testid="am-repeat-interval"
|
data-testid="am-repeat-interval"
|
||||||
>
|
>
|
||||||
<PromDurationInput
|
<PromDurationInput
|
||||||
{...register('repeatIntervalValue', { validate: promDurationValidator })}
|
{...register('repeatIntervalValue', {
|
||||||
|
validate: (value: string) => {
|
||||||
|
const groupInterval = getValues('groupIntervalValue');
|
||||||
|
return repeatIntervalValidator(value, groupInterval);
|
||||||
|
},
|
||||||
|
})}
|
||||||
placeholder={TIMING_OPTIONS_DEFAULTS.repeat_interval}
|
placeholder={TIMING_OPTIONS_DEFAULTS.repeat_interval}
|
||||||
className={styles.promDurationInput}
|
className={styles.promDurationInput}
|
||||||
aria-label="Repeat interval"
|
aria-label="Repeat interval"
|
||||||
|
|||||||
+26
@@ -76,6 +76,32 @@ describe('EditNotificationPolicyForm', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show an error if repeat interval is lower than group interval', async function () {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
|
||||||
|
const onSubmit = jest.fn();
|
||||||
|
renderRouteForm(
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
receiver: 'default',
|
||||||
|
},
|
||||||
|
[{ value: 'default', label: 'Default' }],
|
||||||
|
onSubmit
|
||||||
|
);
|
||||||
|
|
||||||
|
await user.click(ui.overrideTimingsCheckbox.get());
|
||||||
|
|
||||||
|
await user.type(ui.groupWaitInput.get(), '5m25s');
|
||||||
|
await user.type(ui.groupIntervalInput.get(), '35m40s');
|
||||||
|
await user.type(ui.repeatIntervalInput.get(), '30m');
|
||||||
|
|
||||||
|
await user.click(ui.submitBtn.get());
|
||||||
|
|
||||||
|
expect(ui.error.getAll()).toHaveLength(1);
|
||||||
|
expect(ui.error.get().textContent).toBe('Repeat interval should be higher or equal to Group interval');
|
||||||
|
expect(onSubmit).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow resetting existing timing options', async function () {
|
it('should allow resetting existing timing options', async function () {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -32,6 +32,7 @@ import {
|
|||||||
commonGroupByOptions,
|
commonGroupByOptions,
|
||||||
amRouteToFormAmRoute,
|
amRouteToFormAmRoute,
|
||||||
promDurationValidator,
|
promDurationValidator,
|
||||||
|
repeatIntervalValidator,
|
||||||
} from '../../utils/amroutes';
|
} from '../../utils/amroutes';
|
||||||
import { AmRouteReceiver } from '../receivers/grafanaAppReceivers/types';
|
import { AmRouteReceiver } from '../receivers/grafanaAppReceivers/types';
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ export const AmRoutesExpandedForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Form defaultValues={defaultValues} onSubmit={onSubmit} maxWidth="none">
|
<Form defaultValues={defaultValues} onSubmit={onSubmit} maxWidth="none">
|
||||||
{({ control, register, errors, setValue, watch }) => (
|
{({ control, register, errors, setValue, watch, getValues }) => (
|
||||||
<>
|
<>
|
||||||
<input type="hidden" {...register('id')} />
|
<input type="hidden" {...register('id')} />
|
||||||
{/* @ts-ignore-check: react-hook-form made me do this */}
|
{/* @ts-ignore-check: react-hook-form made me do this */}
|
||||||
@@ -247,7 +248,12 @@ export const AmRoutesExpandedForm = ({
|
|||||||
error={errors.repeatIntervalValue?.message}
|
error={errors.repeatIntervalValue?.message}
|
||||||
>
|
>
|
||||||
<PromDurationInput
|
<PromDurationInput
|
||||||
{...register('repeatIntervalValue', { validate: promDurationValidator })}
|
{...register('repeatIntervalValue', {
|
||||||
|
validate: (value: string) => {
|
||||||
|
const groupInterval = getValues('groupIntervalValue');
|
||||||
|
return repeatIntervalValidator(value, groupInterval);
|
||||||
|
},
|
||||||
|
})}
|
||||||
aria-label="Repeat interval value"
|
aria-label="Repeat interval value"
|
||||||
className={formStyles.promDurationInput}
|
className={formStyles.promDurationInput}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { uniqueId } from 'lodash';
|
|||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { MatcherOperator, ObjectMatcher, Route, RouteWithID } from 'app/plugins/datasource/alertmanager/types';
|
import { MatcherOperator, ObjectMatcher, Route, RouteWithID } from 'app/plugins/datasource/alertmanager/types';
|
||||||
|
|
||||||
|
import { safeParseDurationstr } from '../components/rules/EditRuleGroupModal';
|
||||||
import { FormAmRoute } from '../types/amroutes';
|
import { FormAmRoute } from '../types/amroutes';
|
||||||
import { MatcherFieldValue } from '../types/silence-form';
|
import { MatcherFieldValue } from '../types/silence-form';
|
||||||
|
|
||||||
@@ -225,3 +226,27 @@ export function promDurationValidator(duration: string) {
|
|||||||
|
|
||||||
return isValidPrometheusDuration(duration) || 'Invalid duration format. Must be {number}{time_unit}';
|
return isValidPrometheusDuration(duration) || 'Invalid duration format. Must be {number}{time_unit}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const repeatIntervalValidator = (repeatInterval: string, groupInterval: string) => {
|
||||||
|
if (repeatInterval.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validRepeatInterval = promDurationValidator(repeatInterval);
|
||||||
|
const validGroupInterval = promDurationValidator(groupInterval);
|
||||||
|
|
||||||
|
if (validRepeatInterval !== true) {
|
||||||
|
return validRepeatInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validGroupInterval !== true) {
|
||||||
|
return validGroupInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
const repeatDuration = safeParseDurationstr(repeatInterval);
|
||||||
|
const groupDuration = safeParseDurationstr(groupInterval);
|
||||||
|
|
||||||
|
const isRepeatLowerThanGroupDuration = groupDuration !== 0 && repeatDuration < groupDuration;
|
||||||
|
|
||||||
|
return isRepeatLowerThanGroupDuration ? 'Repeat interval should be higher or equal to Group interval' : true;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user