diff --git a/public/app/features/alerting/unified/Templates.test.tsx b/public/app/features/alerting/unified/Templates.test.tsx
index 6d695af5826..99cd7a39d7f 100644
--- a/public/app/features/alerting/unified/Templates.test.tsx
+++ b/public/app/features/alerting/unified/Templates.test.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { Props } from 'react-virtualized-auto-sizer';
-import { render, screen, within } from 'test/test-utils';
-import { byRole } from 'testing-library-selector';
+import { render, screen, waitFor, within } from 'test/test-utils';
+import { byLabelText, byRole } from 'testing-library-selector';
import { CodeEditorProps } from '@grafana/ui/src/components/Monaco/types';
import { AppNotificationList } from 'app/core/components/AppNotifications/AppNotificationList';
@@ -40,6 +40,10 @@ jest.mock('@grafana/ui', () => ({
const ui = {
templateForm: byRole('form', { name: 'Template form' }),
+ form: {
+ title: byLabelText(/Template name/),
+ saveButton: byRole('button', { name: 'Save' }),
+ },
};
const navUrl = {
@@ -77,6 +81,40 @@ describe('Templates routes', () => {
expect(form).toBeInTheDocument();
expect(within(form).getByRole('textbox', { name: /Template name/ })).toHaveValue('');
});
+
+ it('should pass name validation when editing existing template', async () => {
+ const { user } = render(
+ <>
+
+
+ >,
+ { historyOptions: { initialEntries: [navUrl.edit('custom-email')] } }
+ );
+
+ const titleElement = await ui.form.title.find();
+ await waitFor(() => {
+ expect(titleElement).toHaveValue('custom-email');
+ });
+
+ await user.click(ui.form.saveButton.get());
+
+ // No error message should be displayed for a unique name
+ expect(screen.queryByText('Another template with this name already exists')).not.toBeInTheDocument();
+ await waitFor(() => {
+ expect(screen.getByText('Template saved')).toBeInTheDocument();
+ });
+ });
+
+ it('should display error message when creating new template with duplicate name', async () => {
+ const { user } = render(, { historyOptions: { initialEntries: [navUrl.new] } });
+
+ const titleElement = await ui.form.title.find();
+ await user.type(titleElement, 'custom-email');
+
+ await user.click(ui.form.saveButton.get());
+
+ expect(screen.getByText('Another template with this name already exists')).toBeInTheDocument();
+ });
});
describe('Templates K8s API', () => {
diff --git a/public/app/features/alerting/unified/components/contact-points/useNotificationTemplates.ts b/public/app/features/alerting/unified/components/contact-points/useNotificationTemplates.ts
index e98aca41847..c20e2dc1650 100644
--- a/public/app/features/alerting/unified/components/contact-points/useNotificationTemplates.ts
+++ b/public/app/features/alerting/unified/components/contact-points/useNotificationTemplates.ts
@@ -281,7 +281,15 @@ export function useDeleteNotificationTemplate({ alertmanager }: BaseAlertmanager
return k8sApiSupported ? deleteUsingK8sApi : deleteUsingConfigFileApi;
}
-export function useValidateNotificationTemplate({ alertmanager }: BaseAlertmanagerArgs) {
+interface ValidateNotificationTemplateParams {
+ alertmanager: string;
+ originalTemplate?: NotificationTemplate;
+}
+
+export function useValidateNotificationTemplate({
+ alertmanager,
+ originalTemplate,
+}: ValidateNotificationTemplateParams) {
const { useLazyGetAlertmanagerConfigurationQuery } = alertmanagerApi;
const [fetchAmConfig] = useLazyGetAlertmanagerConfigurationQuery();
@@ -294,6 +302,11 @@ export function useValidateNotificationTemplate({ alertmanager }: BaseAlertmanag
return true;
}
+ if (originalTemplate?.title === name) {
+ // If original template is defined we update existing template so name will not be unique but it's ok
+ return true;
+ }
+
const amConfig = await fetchAmConfig(alertmanager).unwrap();
const templates = amConfigToTemplates(amConfig);
const templateOfThisNameExists = templates.some((t) => t.title === name);
diff --git a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx
index c306701172b..8dadda756e1 100644
--- a/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx
+++ b/public/app/features/alerting/unified/components/receivers/TemplateForm.tsx
@@ -93,7 +93,7 @@ export const TemplateForm = ({ originalTemplate, prefill, alertmanager }: Props)
const createNewTemplate = useCreateNotificationTemplate({ alertmanager });
const updateTemplate = useUpdateNotificationTemplate({ alertmanager });
- const { titleIsUnique } = useValidateNotificationTemplate({ alertmanager });
+ const { titleIsUnique } = useValidateNotificationTemplate({ alertmanager, originalTemplate });
useCleanup((state) => (state.unifiedAlerting.saveAMConfig = initialAsyncRequestState));
const formRef = useRef(null);