The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/alerting/unified/Templates.test.tsx

175 lines
6.0 KiB

import { InitialEntry } from 'history/createMemoryHistory';
import * as React from 'react';
import { Route, Routes } from 'react-router-dom-v5-compat';
import { Props } from 'react-virtualized-auto-sizer';
import { render, screen, waitFor, within } from 'test/test-utils';
import { byLabelText, byRole } from 'testing-library-selector';
import { CodeEditor } from '@grafana/ui';
import { AppNotificationList } from 'app/core/components/AppNotifications/AppNotificationList';
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
import { testWithFeatureToggles } from 'app/features/alerting/unified/test/test-utils';
import { AccessControlAction } from 'app/types';
import Templates from './Templates';
import { grantUserPermissions } from './mocks';
type CodeEditorProps = React.ComponentProps<typeof CodeEditor>;
jest.mock('app/core/components/AppChrome/AppChromeUpdate', () => ({
AppChromeUpdate: ({ actions }: { actions: React.ReactNode }) => <div>{actions}</div>,
}));
//mock updateDefinesWithUniqueValue
jest.mock('app/features/alerting/unified/utils/templates', () => ({
...jest.requireActual('app/features/alerting/unified/utils/templates'),
updateDefinesWithUniqueValue: (templateContent: string) => {
return templateContent.replace(/custom-email/g, 'custom-email_NEW');
},
}));
jest.mock(
'react-virtualized-auto-sizer',
() =>
({ children }: Props) =>
children({ width: 1000, height: 1000, scaledWidth: 1, scaledHeight: 1 })
);
jest.mock('@grafana/ui', () => ({
...jest.requireActual('@grafana/ui'),
CodeEditor: ({ value, onChange }: CodeEditorProps) => (
<textarea data-testid="code-editor" value={value} onChange={(e) => onChange?.(e.target.value)} />
),
}));
const ui = {
templateForm: byRole('form', { name: 'Template form' }),
form: {
title: byLabelText(/Template group name/),
saveButton: byRole('button', { name: 'Save' }),
},
};
const navUrl = {
edit: (name: string) => `/alerting/notifications/templates/${name}/edit?alertmanager=grafana`,
duplicate: (name: string) => `/alerting/notifications/templates/${name}/duplicate?alertmanager=grafana`,
new: `/alerting/notifications/templates/new`,
};
setupMswServer();
beforeEach(() => {
grantUserPermissions([AccessControlAction.AlertingNotificationsRead, AccessControlAction.AlertingNotificationsWrite]);
});
const setup = (initialEntries: InitialEntry[]) => {
return render(
<>
<AppNotificationList />
<Routes>
<Route path="/alerting/notifications/templates/*" element={<Templates />} />
</Routes>
</>,
{
historyOptions: { initialEntries },
}
);
};
describe('Templates routes', () => {
it('allows duplication of template with spaces in name', async () => {
setup([navUrl.duplicate('template%20with%20spaces')]);
expect(await screen.findByText('Edit payload')).toBeInTheDocument();
});
it('allows editing of template with spaces in name', async () => {
setup([navUrl.edit('template%20with%20spaces')]);
expect(await screen.findByText('Edit payload')).toBeInTheDocument();
});
it('renders empty template form', async () => {
setup([navUrl.new]);
const form = await ui.templateForm.find();
expect(form).toBeInTheDocument();
expect(within(form).getByRole('textbox', { name: /Template group name/ })).toHaveValue('');
});
it('should pass name validation when editing existing template', async () => {
const { user } = setup([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 } = setup([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', () => {
testWithFeatureToggles(['alertingApiServer']);
it('form edit renders with correct form values', async () => {
setup([navUrl.edit('k8s-custom-email-resource-name')]);
const form = await ui.templateForm.find();
expect(form).toBeInTheDocument();
expect(within(form).getByRole('textbox', { name: /Template group name/ })).toHaveValue('custom-email');
expect(within(form).getAllByTestId('code-editor')[0]).toHaveValue(
'{{ define "custom-email" }} Custom email template {{ end }}'
);
});
it('renders duplicate template form with correct values', async () => {
setup([navUrl.duplicate('k8s-custom-email-resource-name')]);
const form = await ui.templateForm.find();
expect(form).toBeInTheDocument();
expect(within(form).getByRole('textbox', { name: /Template group name/ })).toHaveValue('custom-email (copy)');
expect(within(form).getAllByTestId('code-editor')[0]).toHaveTextContent(
'{{ define "custom-email_NEW" }} Custom email template {{ end }}'
);
});
it('updates a template', async () => {
const { user } = setup([navUrl.edit('k8s-custom-email-resource-name')]);
const form = await ui.templateForm.find();
const templateEditor = within(form).getAllByTestId('code-editor')[0];
await user.clear(templateEditor);
await user.type(templateEditor, '{{ define "custom-email" }}Updated custom email template{{ end }}');
await user.click(screen.getByRole('button', { name: 'Save' }));
expect(await screen.findByRole('status', { name: 'Template saved' })).toHaveTextContent(
'Template custom-email has been saved'
);
expect(ui.templateForm.query()).not.toBeInTheDocument();
});
});