AlertmanagerConfig.test.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { render, waitFor } from '@testing-library/react';
  2. import userEvent from '@testing-library/user-event';
  3. import React from 'react';
  4. import { Provider } from 'react-redux';
  5. import { Router } from 'react-router-dom';
  6. import { byLabelText, byRole, byTestId } from 'testing-library-selector';
  7. import { locationService, setDataSourceSrv } from '@grafana/runtime';
  8. import { contextSrv } from 'app/core/services/context_srv';
  9. import store from 'app/core/store';
  10. import {
  11. AlertManagerCortexConfig,
  12. AlertManagerDataSourceJsonData,
  13. AlertManagerImplementation,
  14. } from 'app/plugins/datasource/alertmanager/types';
  15. import { configureStore } from 'app/store/configureStore';
  16. import {
  17. fetchAlertManagerConfig,
  18. deleteAlertManagerConfig,
  19. updateAlertManagerConfig,
  20. fetchStatus,
  21. } from '../../api/alertmanager';
  22. import {
  23. disableRBAC,
  24. mockDataSource,
  25. MockDataSourceSrv,
  26. someCloudAlertManagerConfig,
  27. someCloudAlertManagerStatus,
  28. } from '../../mocks';
  29. import { getAllDataSources } from '../../utils/config';
  30. import { ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, ALERTMANAGER_NAME_QUERY_KEY } from '../../utils/constants';
  31. import { DataSourceType } from '../../utils/datasource';
  32. import AlertmanagerConfig from './AlertmanagerConfig';
  33. jest.mock('../../api/alertmanager');
  34. jest.mock('../../api/grafana');
  35. jest.mock('../../utils/config');
  36. const mocks = {
  37. getAllDataSources: jest.mocked(getAllDataSources),
  38. api: {
  39. fetchConfig: jest.mocked(fetchAlertManagerConfig),
  40. deleteAlertManagerConfig: jest.mocked(deleteAlertManagerConfig),
  41. updateAlertManagerConfig: jest.mocked(updateAlertManagerConfig),
  42. fetchStatus: jest.mocked(fetchStatus),
  43. },
  44. };
  45. const renderAdminPage = (alertManagerSourceName?: string) => {
  46. const store = configureStore();
  47. locationService.push(
  48. '/alerting/notifications' +
  49. (alertManagerSourceName ? `?${ALERTMANAGER_NAME_QUERY_KEY}=${alertManagerSourceName}` : '')
  50. );
  51. return render(
  52. <Provider store={store}>
  53. <Router history={locationService.getHistory()}>
  54. <AlertmanagerConfig />
  55. </Router>
  56. </Provider>
  57. );
  58. };
  59. const dataSources = {
  60. alertManager: mockDataSource({
  61. name: 'CloudManager',
  62. type: DataSourceType.Alertmanager,
  63. }),
  64. promAlertManager: mockDataSource<AlertManagerDataSourceJsonData>({
  65. name: 'PromManager',
  66. type: DataSourceType.Alertmanager,
  67. jsonData: {
  68. implementation: AlertManagerImplementation.prometheus,
  69. },
  70. }),
  71. };
  72. const ui = {
  73. confirmButton: byRole('button', { name: /Confirm Modal Danger Button/ }),
  74. resetButton: byRole('button', { name: /Reset configuration/ }),
  75. saveButton: byRole('button', { name: /Save/ }),
  76. configInput: byLabelText<HTMLTextAreaElement>(/Configuration/),
  77. readOnlyConfig: byTestId('readonly-config'),
  78. };
  79. describe('Admin config', () => {
  80. beforeEach(() => {
  81. jest.resetAllMocks();
  82. mocks.getAllDataSources.mockReturnValue(Object.values(dataSources));
  83. setDataSourceSrv(new MockDataSourceSrv(dataSources));
  84. contextSrv.isGrafanaAdmin = true;
  85. store.delete(ALERTMANAGER_NAME_LOCAL_STORAGE_KEY);
  86. disableRBAC();
  87. });
  88. it('Reset alertmanager config', async () => {
  89. mocks.api.fetchConfig.mockResolvedValue({
  90. template_files: {
  91. foo: 'bar',
  92. },
  93. alertmanager_config: {},
  94. });
  95. mocks.api.deleteAlertManagerConfig.mockResolvedValue();
  96. await renderAdminPage(dataSources.alertManager.name);
  97. await userEvent.click(await ui.resetButton.find());
  98. await userEvent.click(ui.confirmButton.get());
  99. await waitFor(() => expect(mocks.api.deleteAlertManagerConfig).toHaveBeenCalled());
  100. expect(ui.confirmButton.query()).not.toBeInTheDocument();
  101. });
  102. it('Edit and save alertmanager config', async () => {
  103. let savedConfig: AlertManagerCortexConfig | undefined = undefined;
  104. const defaultConfig = {
  105. template_files: {
  106. foo: 'bar',
  107. },
  108. alertmanager_config: {},
  109. };
  110. const newConfig = {
  111. template_files: {
  112. bar: 'baz',
  113. },
  114. alertmanager_config: {},
  115. };
  116. mocks.api.fetchConfig.mockImplementation(() => Promise.resolve(savedConfig ?? defaultConfig));
  117. mocks.api.updateAlertManagerConfig.mockResolvedValue();
  118. await renderAdminPage(dataSources.alertManager.name);
  119. const input = await ui.configInput.find();
  120. expect(input.value).toEqual(JSON.stringify(defaultConfig, null, 2));
  121. await userEvent.clear(input);
  122. // What is this regex replace doing? in userEvent v13, '{' and '[' are special characters.
  123. // To get the literal character, you have to escape them by typing '{{' or '[['.
  124. // See https://github.com/testing-library/user-event/issues/584.
  125. await userEvent.type(input, JSON.stringify(newConfig, null, 2).replace(/[{[]/g, '$&$&'));
  126. await userEvent.click(ui.saveButton.get());
  127. await waitFor(() => expect(mocks.api.updateAlertManagerConfig).toHaveBeenCalled());
  128. await waitFor(() => expect(mocks.api.fetchConfig).toHaveBeenCalledTimes(3));
  129. expect(input.value).toEqual(JSON.stringify(newConfig, null, 2));
  130. });
  131. it('Read-only when using Prometheus Alertmanager', async () => {
  132. mocks.api.fetchStatus.mockResolvedValue({
  133. ...someCloudAlertManagerStatus,
  134. config: someCloudAlertManagerConfig.alertmanager_config,
  135. });
  136. await renderAdminPage(dataSources.promAlertManager.name);
  137. await ui.readOnlyConfig.find();
  138. expect(ui.configInput.query()).not.toBeInTheDocument();
  139. expect(ui.resetButton.query()).not.toBeInTheDocument();
  140. expect(ui.saveButton.query()).not.toBeInTheDocument();
  141. expect(mocks.api.fetchConfig).not.toHaveBeenCalled();
  142. expect(mocks.api.fetchStatus).toHaveBeenCalledTimes(1);
  143. });
  144. });