mirror of https://github.com/grafana/grafana.git
				
				
				
			Alerting: Add test for creating an alert rule with simplified routing. (#80610)
* Add test for creating an alert rule with simplified routing * Fix mocking folders after merging from main (folder uid change)
This commit is contained in:
		
							parent
							
								
									7a741a31bd
								
							
						
					
					
						commit
						0e7c0d25fe
					
				|  | @ -0,0 +1,433 @@ | ||||||
|  | import { render, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react'; | ||||||
|  | import userEvent from '@testing-library/user-event'; | ||||||
|  | import React from 'react'; | ||||||
|  | import { Route } from 'react-router-dom'; | ||||||
|  | import { TestProvider } from 'test/helpers/TestProvider'; | ||||||
|  | import { ui } from 'test/helpers/alertingRuleEditor'; | ||||||
|  | import { clickSelectOption } from 'test/helpers/selectOptionInTest'; | ||||||
|  | import { byRole } from 'testing-library-selector'; | ||||||
|  | 
 | ||||||
|  | import { config, locationService, setDataSourceSrv } from '@grafana/runtime'; | ||||||
|  | import { contextSrv } from 'app/core/services/context_srv'; | ||||||
|  | import RuleEditor from 'app/features/alerting/unified/RuleEditor'; | ||||||
|  | import { discoverFeatures } from 'app/features/alerting/unified/api/buildInfo'; | ||||||
|  | import { | ||||||
|  |   fetchRulerRules, | ||||||
|  |   fetchRulerRulesGroup, | ||||||
|  |   fetchRulerRulesNamespace, | ||||||
|  |   setRulerRuleGroup, | ||||||
|  | } from 'app/features/alerting/unified/api/ruler'; | ||||||
|  | import * as useContactPoints from 'app/features/alerting/unified/components/contact-points/useContactPoints'; | ||||||
|  | import * as dsByPermission from 'app/features/alerting/unified/hooks/useAlertManagerSources'; | ||||||
|  | import { MockDataSourceSrv, grantUserPermissions, mockDataSource } from 'app/features/alerting/unified/mocks'; | ||||||
|  | import { AlertmanagerProvider } from 'app/features/alerting/unified/state/AlertmanagerContext'; | ||||||
|  | import { fetchRulerRulesIfNotFetchedYet } from 'app/features/alerting/unified/state/actions'; | ||||||
|  | import * as utils_config from 'app/features/alerting/unified/utils/config'; | ||||||
|  | import { | ||||||
|  |   AlertManagerDataSource, | ||||||
|  |   DataSourceType, | ||||||
|  |   GRAFANA_DATASOURCE_NAME, | ||||||
|  |   GRAFANA_RULES_SOURCE_NAME, | ||||||
|  |   getAlertManagerDataSourcesByPermission, | ||||||
|  |   useGetAlertManagerDataSourcesByPermissionAndConfig, | ||||||
|  | } from 'app/features/alerting/unified/utils/datasource'; | ||||||
|  | import { getDefaultQueries } from 'app/features/alerting/unified/utils/rule-form'; | ||||||
|  | import { searchFolders } from 'app/features/manage-dashboards/state/actions'; | ||||||
|  | import { DashboardSearchHit, DashboardSearchItemType } from 'app/features/search/types'; | ||||||
|  | import { AccessControlAction } from 'app/types'; | ||||||
|  | import { GrafanaAlertStateDecision, PromApplication } from 'app/types/unified-alerting-dto'; | ||||||
|  | 
 | ||||||
|  | import { RECEIVER_META_KEY } from '../../../contact-points/useContactPoints'; | ||||||
|  | import { ContactPointWithMetadata } from '../../../contact-points/utils'; | ||||||
|  | import { ExpressionEditorProps } from '../../ExpressionEditor'; | ||||||
|  | 
 | ||||||
|  | jest.mock('app/features/alerting/unified/components/rule-editor/ExpressionEditor', () => ({ | ||||||
|  |   // eslint-disable-next-line react/display-name
 | ||||||
|  |   ExpressionEditor: ({ value, onChange }: ExpressionEditorProps) => ( | ||||||
|  |     <input value={value} data-testid="expr" onChange={(e) => onChange(e.target.value)} /> | ||||||
|  |   ), | ||||||
|  | })); | ||||||
|  | 
 | ||||||
|  | jest.mock('app/features/alerting/unified/api/buildInfo'); | ||||||
|  | jest.mock('app/features/alerting/unified/api/ruler'); | ||||||
|  | jest.mock('app/features/manage-dashboards/state/actions'); | ||||||
|  | 
 | ||||||
|  | jest.mock('app/core/components/AppChrome/AppChromeUpdate', () => ({ | ||||||
|  |   AppChromeUpdate: ({ actions }: { actions: React.ReactNode }) => <div>{actions}</div>, | ||||||
|  | })); | ||||||
|  | 
 | ||||||
|  | // there's no angular scope in test and things go terribly wrong when trying to render the query editor row.
 | ||||||
|  | // lets just skip it
 | ||||||
|  | jest.mock('app/features/query/components/QueryEditorRow', () => ({ | ||||||
|  |   // eslint-disable-next-line react/display-name
 | ||||||
|  |   QueryEditorRow: () => <p>hi</p>, | ||||||
|  | })); | ||||||
|  | 
 | ||||||
|  | // simplified routing mocks
 | ||||||
|  | const grafanaAlertManagerDataSource: AlertManagerDataSource = { | ||||||
|  |   name: GRAFANA_RULES_SOURCE_NAME, | ||||||
|  |   imgUrl: 'public/img/grafana_icon.svg', | ||||||
|  |   hasConfigurationAPI: true, | ||||||
|  | }; | ||||||
|  | jest.mock('app/features/alerting/unified/utils/datasource', () => { | ||||||
|  |   return { | ||||||
|  |     ...jest.requireActual('app/features/alerting/unified/utils/datasource'), | ||||||
|  |     getAlertManagerDataSourcesByPermission: jest.fn(), | ||||||
|  |     useGetAlertManagerDataSourcesByPermissionAndConfig: jest.fn(), | ||||||
|  |     getAlertmanagerDataSourceByName: jest.fn(), | ||||||
|  |   }; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const user = userEvent.setup(); | ||||||
|  | 
 | ||||||
|  | jest.spyOn(utils_config, 'getAllDataSources'); | ||||||
|  | jest.spyOn(dsByPermission, 'useAlertManagersByPermission'); | ||||||
|  | jest.spyOn(useContactPoints, 'useContactPointsWithStatus'); | ||||||
|  | 
 | ||||||
|  | jest.setTimeout(60 * 1000); | ||||||
|  | 
 | ||||||
|  | const mocks = { | ||||||
|  |   getAllDataSources: jest.mocked(utils_config.getAllDataSources), | ||||||
|  |   searchFolders: jest.mocked(searchFolders), | ||||||
|  |   useContactPointsWithStatus: jest.mocked(useContactPoints.useContactPointsWithStatus), | ||||||
|  |   useGetAlertManagerDataSourcesByPermissionAndConfig: jest.mocked(useGetAlertManagerDataSourcesByPermissionAndConfig), | ||||||
|  |   getAlertManagerDataSourcesByPermission: jest.mocked(getAlertManagerDataSourcesByPermission), | ||||||
|  |   api: { | ||||||
|  |     discoverFeatures: jest.mocked(discoverFeatures), | ||||||
|  |     fetchRulerRulesGroup: jest.mocked(fetchRulerRulesGroup), | ||||||
|  |     setRulerRuleGroup: jest.mocked(setRulerRuleGroup), | ||||||
|  |     fetchRulerRulesNamespace: jest.mocked(fetchRulerRulesNamespace), | ||||||
|  |     fetchRulerRules: jest.mocked(fetchRulerRules), | ||||||
|  |     fetchRulerRulesIfNotFetchedYet: jest.mocked(fetchRulerRulesIfNotFetchedYet), | ||||||
|  |   }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | describe('Can create a new grafana managed alert unsing simplified routing', () => { | ||||||
|  |   beforeEach(() => { | ||||||
|  |     jest.clearAllMocks(); | ||||||
|  |     contextSrv.isEditor = true; | ||||||
|  |     contextSrv.hasEditPermissionInFolders = true; | ||||||
|  |     grantUserPermissions([ | ||||||
|  |       AccessControlAction.AlertingRuleRead, | ||||||
|  |       AccessControlAction.AlertingRuleUpdate, | ||||||
|  |       AccessControlAction.AlertingRuleDelete, | ||||||
|  |       AccessControlAction.AlertingRuleCreate, | ||||||
|  |       AccessControlAction.DataSourcesRead, | ||||||
|  |       AccessControlAction.DataSourcesWrite, | ||||||
|  |       AccessControlAction.DataSourcesCreate, | ||||||
|  |       AccessControlAction.FoldersWrite, | ||||||
|  |       AccessControlAction.FoldersRead, | ||||||
|  |       AccessControlAction.AlertingRuleExternalRead, | ||||||
|  |       AccessControlAction.AlertingRuleExternalWrite, | ||||||
|  |       AccessControlAction.AlertingNotificationsRead, | ||||||
|  |       AccessControlAction.AlertingNotificationsWrite, | ||||||
|  |     ]); | ||||||
|  |     mocks.getAlertManagerDataSourcesByPermission.mockReturnValue({ | ||||||
|  |       availableInternalDataSources: [grafanaAlertManagerDataSource], | ||||||
|  |       availableExternalDataSources: [], | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     mocks.useGetAlertManagerDataSourcesByPermissionAndConfig.mockReturnValue([grafanaAlertManagerDataSource]); | ||||||
|  | 
 | ||||||
|  |     jest.mocked(dsByPermission.useAlertManagersByPermission).mockReturnValue({ | ||||||
|  |       availableInternalDataSources: [grafanaAlertManagerDataSource], | ||||||
|  |       availableExternalDataSources: [], | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const dataSources = { | ||||||
|  |     default: mockDataSource( | ||||||
|  |       { | ||||||
|  |         type: 'prometheus', | ||||||
|  |         name: 'Prom', | ||||||
|  |         isDefault: true, | ||||||
|  |       }, | ||||||
|  |       { alerting: false } | ||||||
|  |     ), | ||||||
|  |     am: mockDataSource({ | ||||||
|  |       name: 'Alertmanager', | ||||||
|  |       type: DataSourceType.Alertmanager, | ||||||
|  |     }), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   it('cannot create new grafana managed alert when using simplified routing and not selecting a contact point', async () => { | ||||||
|  |     // no contact points found
 | ||||||
|  |     mocks.useContactPointsWithStatus.mockReturnValue({ | ||||||
|  |       contactPoints: [], | ||||||
|  |       isLoading: false, | ||||||
|  |       error: undefined, | ||||||
|  |       refetchReceivers: jest.fn(), | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     setDataSourceSrv(new MockDataSourceSrv(dataSources)); | ||||||
|  |     mocks.getAllDataSources.mockReturnValue(Object.values(dataSources)); | ||||||
|  |     mocks.api.setRulerRuleGroup.mockResolvedValue(); | ||||||
|  |     mocks.api.fetchRulerRulesNamespace.mockResolvedValue([]); | ||||||
|  |     mocks.api.fetchRulerRulesGroup.mockResolvedValue({ | ||||||
|  |       name: 'group2', | ||||||
|  |       rules: [], | ||||||
|  |     }); | ||||||
|  |     mocks.api.fetchRulerRules.mockResolvedValue({ | ||||||
|  |       'Folder A': [ | ||||||
|  |         { | ||||||
|  |           interval: '1m', | ||||||
|  |           name: 'group1', | ||||||
|  |           rules: [ | ||||||
|  |             { | ||||||
|  |               annotations: { description: 'some description', summary: 'some summary' }, | ||||||
|  |               labels: { severity: 'warn', team: 'the a-team' }, | ||||||
|  |               for: '5m', | ||||||
|  |               grafana_alert: { | ||||||
|  |                 uid: '23', | ||||||
|  |                 namespace_uid: 'abcd', | ||||||
|  |                 condition: 'B', | ||||||
|  |                 data: getDefaultQueries(), | ||||||
|  |                 exec_err_state: GrafanaAlertStateDecision.Error, | ||||||
|  |                 no_data_state: GrafanaAlertStateDecision.NoData, | ||||||
|  |                 title: 'my great new rule', | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       namespace2: [ | ||||||
|  |         { | ||||||
|  |           interval: '1m', | ||||||
|  |           name: 'group1', | ||||||
|  |           rules: [ | ||||||
|  |             { | ||||||
|  |               annotations: { description: 'some description', summary: 'some summary' }, | ||||||
|  |               labels: { severity: 'warn', team: 'the a-team' }, | ||||||
|  |               for: '5m', | ||||||
|  |               grafana_alert: { | ||||||
|  |                 uid: '23', | ||||||
|  |                 namespace_uid: 'b', | ||||||
|  |                 condition: 'B', | ||||||
|  |                 data: getDefaultQueries(), | ||||||
|  |                 exec_err_state: GrafanaAlertStateDecision.Error, | ||||||
|  |                 no_data_state: GrafanaAlertStateDecision.NoData, | ||||||
|  |                 title: 'my great new rule', | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |     mocks.searchFolders.mockResolvedValue([ | ||||||
|  |       { | ||||||
|  |         title: 'Folder A', | ||||||
|  |         uid: 'abcd', | ||||||
|  |         id: 1, | ||||||
|  |         type: DashboardSearchItemType.DashDB, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         title: 'Folder B', | ||||||
|  |         id: 2, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         title: 'Folder / with slash', | ||||||
|  |         id: 2, | ||||||
|  |         uid: 'b', | ||||||
|  |         type: DashboardSearchItemType.DashDB, | ||||||
|  |       }, | ||||||
|  |     ] as DashboardSearchHit[]); | ||||||
|  | 
 | ||||||
|  |     mocks.api.discoverFeatures.mockResolvedValue({ | ||||||
|  |       application: PromApplication.Prometheus, | ||||||
|  |       features: { | ||||||
|  |         rulerApiEnabled: false, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |     config.featureToggles.alertingSimplifiedRouting = true; | ||||||
|  |     renderSimplifiedRuleEditor(); | ||||||
|  |     await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); | ||||||
|  | 
 | ||||||
|  |     await user.type(await ui.inputs.name.find(), 'my great new rule'); | ||||||
|  | 
 | ||||||
|  |     const folderInput = await ui.inputs.folder.find(); | ||||||
|  |     await clickSelectOption(folderInput, 'Folder A'); | ||||||
|  |     const groupInput = await ui.inputs.group.find(); | ||||||
|  |     await user.click(byRole('combobox').get(groupInput)); | ||||||
|  |     await clickSelectOption(groupInput, 'group1'); | ||||||
|  |     //select contact point routing
 | ||||||
|  |     await user.click(ui.inputs.simplifiedRouting.contactPointRouting.get()); | ||||||
|  |     // do not select a contact point
 | ||||||
|  |     // save and check that call to backend was not made
 | ||||||
|  |     await user.click(ui.buttons.saveAndExit.get()); | ||||||
|  |     await waitFor(() => { | ||||||
|  |       expect(screen.getByText('Contact point is required.')).toBeInTheDocument(); | ||||||
|  |       expect(mocks.api.setRulerRuleGroup).not.toHaveBeenCalled(); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   it('can create new grafana managed alert when using simplified routing and selecting a contact point', async () => { | ||||||
|  |     const contactPointsAvailable: ContactPointWithMetadata[] = [ | ||||||
|  |       { | ||||||
|  |         name: 'contact_point1', | ||||||
|  |         grafana_managed_receiver_configs: [ | ||||||
|  |           { | ||||||
|  |             name: 'contact_point1', | ||||||
|  |             type: 'email', | ||||||
|  |             disableResolveMessage: false, | ||||||
|  |             [RECEIVER_META_KEY]: { | ||||||
|  |               name: 'contact_point1', | ||||||
|  |               description: 'contact_point1 description', | ||||||
|  |             }, | ||||||
|  |             settings: {}, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |         numberOfPolicies: 0, | ||||||
|  |       }, | ||||||
|  |     ]; | ||||||
|  |     mocks.useContactPointsWithStatus.mockReturnValue({ | ||||||
|  |       contactPoints: contactPointsAvailable, | ||||||
|  |       isLoading: false, | ||||||
|  |       error: undefined, | ||||||
|  |       refetchReceivers: jest.fn(), | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     setDataSourceSrv(new MockDataSourceSrv(dataSources)); | ||||||
|  |     mocks.getAllDataSources.mockReturnValue(Object.values(dataSources)); | ||||||
|  |     mocks.api.setRulerRuleGroup.mockResolvedValue(); | ||||||
|  |     mocks.api.fetchRulerRulesNamespace.mockResolvedValue([]); | ||||||
|  |     mocks.api.fetchRulerRulesGroup.mockResolvedValue({ | ||||||
|  |       name: 'group2', | ||||||
|  |       rules: [], | ||||||
|  |     }); | ||||||
|  |     mocks.api.fetchRulerRules.mockResolvedValue({ | ||||||
|  |       'Folder A': [ | ||||||
|  |         { | ||||||
|  |           interval: '1m', | ||||||
|  |           name: 'group1', | ||||||
|  |           rules: [ | ||||||
|  |             { | ||||||
|  |               annotations: { description: 'some description', summary: 'some summary' }, | ||||||
|  |               labels: { severity: 'warn', team: 'the a-team' }, | ||||||
|  |               for: '5m', | ||||||
|  |               grafana_alert: { | ||||||
|  |                 uid: '23', | ||||||
|  |                 namespace_uid: 'abcd', | ||||||
|  |                 condition: 'B', | ||||||
|  |                 data: getDefaultQueries(), | ||||||
|  |                 exec_err_state: GrafanaAlertStateDecision.Error, | ||||||
|  |                 no_data_state: GrafanaAlertStateDecision.NoData, | ||||||
|  |                 title: 'my great new rule', | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       namespace2: [ | ||||||
|  |         { | ||||||
|  |           interval: '1m', | ||||||
|  |           name: 'group1', | ||||||
|  |           rules: [ | ||||||
|  |             { | ||||||
|  |               annotations: { description: 'some description', summary: 'some summary' }, | ||||||
|  |               labels: { severity: 'warn', team: 'the a-team' }, | ||||||
|  |               for: '5m', | ||||||
|  |               grafana_alert: { | ||||||
|  |                 uid: '23', | ||||||
|  |                 namespace_uid: 'b', | ||||||
|  |                 condition: 'B', | ||||||
|  |                 data: getDefaultQueries(), | ||||||
|  |                 exec_err_state: GrafanaAlertStateDecision.Error, | ||||||
|  |                 no_data_state: GrafanaAlertStateDecision.NoData, | ||||||
|  |                 title: 'my great new rule', | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |     mocks.searchFolders.mockResolvedValue([ | ||||||
|  |       { | ||||||
|  |         title: 'Folder A', | ||||||
|  |         uid: 'abcd', | ||||||
|  |         id: 1, | ||||||
|  |         type: DashboardSearchItemType.DashDB, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         title: 'Folder B', | ||||||
|  |         id: 2, | ||||||
|  |         uid: 'b', | ||||||
|  |         type: DashboardSearchItemType.DashDB, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         title: 'Folder / with slash', | ||||||
|  |         uid: 'c', | ||||||
|  |         id: 2, | ||||||
|  |         type: DashboardSearchItemType.DashDB, | ||||||
|  |       }, | ||||||
|  |     ] as DashboardSearchHit[]); | ||||||
|  | 
 | ||||||
|  |     mocks.api.discoverFeatures.mockResolvedValue({ | ||||||
|  |       application: PromApplication.Prometheus, | ||||||
|  |       features: { | ||||||
|  |         rulerApiEnabled: false, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |     config.featureToggles.alertingSimplifiedRouting = true; | ||||||
|  |     renderSimplifiedRuleEditor(); | ||||||
|  |     await waitForElementToBeRemoved(screen.getAllByTestId('Spinner')); | ||||||
|  | 
 | ||||||
|  |     await user.type(await ui.inputs.name.find(), 'my great new rule'); | ||||||
|  | 
 | ||||||
|  |     const folderInput = await ui.inputs.folder.find(); | ||||||
|  |     await clickSelectOption(folderInput, 'Folder A'); | ||||||
|  |     const groupInput = await ui.inputs.group.find(); | ||||||
|  |     await user.click(byRole('combobox').get(groupInput)); | ||||||
|  |     await clickSelectOption(groupInput, 'group1'); | ||||||
|  |     //select contact point routing
 | ||||||
|  |     await user.click(ui.inputs.simplifiedRouting.contactPointRouting.get()); | ||||||
|  |     const contactPointInput = await ui.inputs.simplifiedRouting.contactPoint.find(); | ||||||
|  |     await user.click(byRole('combobox').get(contactPointInput)); | ||||||
|  |     await clickSelectOption(contactPointInput, 'contact_point1'); | ||||||
|  | 
 | ||||||
|  |     // save and check what was sent to backend
 | ||||||
|  |     await user.click(ui.buttons.saveAndExit.get()); | ||||||
|  |     await waitFor(() => expect(mocks.api.setRulerRuleGroup).toHaveBeenCalled()); | ||||||
|  |     expect(mocks.api.setRulerRuleGroup).toHaveBeenCalledWith( | ||||||
|  |       { dataSourceName: GRAFANA_RULES_SOURCE_NAME, apiVersion: 'legacy' }, | ||||||
|  |       'abcd', | ||||||
|  |       { | ||||||
|  |         interval: '1m', | ||||||
|  |         name: 'group1', | ||||||
|  |         rules: [ | ||||||
|  |           { | ||||||
|  |             annotations: {}, | ||||||
|  |             labels: {}, | ||||||
|  |             for: '5m', | ||||||
|  |             grafana_alert: { | ||||||
|  |               condition: 'B', | ||||||
|  |               data: getDefaultQueries(), | ||||||
|  |               exec_err_state: GrafanaAlertStateDecision.Error, | ||||||
|  |               is_paused: false, | ||||||
|  |               no_data_state: 'NoData', | ||||||
|  |               title: 'my great new rule', | ||||||
|  |               notification_settings: { | ||||||
|  |                 group_by: undefined, | ||||||
|  |                 group_interval: undefined, | ||||||
|  |                 group_wait: undefined, | ||||||
|  |                 mute_timings: undefined, | ||||||
|  |                 receiver: 'contact_point1', | ||||||
|  |                 repeat_interval: undefined, | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       } | ||||||
|  |     ); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | function renderSimplifiedRuleEditor() { | ||||||
|  |   locationService.push(`/alerting/new/alerting`); | ||||||
|  | 
 | ||||||
|  |   return render( | ||||||
|  |     <TestProvider> | ||||||
|  |       <AlertmanagerProvider alertmanagerSourceName={GRAFANA_DATASOURCE_NAME} accessType="notification"> | ||||||
|  |         <Route path={['/alerting/new/:type', '/alerting/:id/edit']} component={RuleEditor} /> | ||||||
|  |       </AlertmanagerProvider> | ||||||
|  |     </TestProvider> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | @ -78,7 +78,7 @@ export function ContactPointSelector({ | ||||||
|   return ( |   return ( | ||||||
|     <Stack direction="column"> |     <Stack direction="column"> | ||||||
|       <Stack direction="row" alignItems="center"> |       <Stack direction="row" alignItems="center"> | ||||||
|         <Field label="Contact point"> |         <Field label="Contact point" data-testid="contact-point-picker"> | ||||||
|           <InputControl |           <InputControl | ||||||
|             render={({ field: { onChange, ref, ...field }, fieldState: { error } }) => ( |             render={({ field: { onChange, ref, ...field }, fieldState: { error } }) => ( | ||||||
|               <> |               <> | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import { render } from '@testing-library/react'; | import { render } from '@testing-library/react'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import { Route } from 'react-router-dom'; | import { Route } from 'react-router-dom'; | ||||||
| import { byRole, byTestId } from 'testing-library-selector'; | import { byRole, byTestId, byText } from 'testing-library-selector'; | ||||||
| 
 | 
 | ||||||
| import { selectors } from '@grafana/e2e-selectors'; | import { selectors } from '@grafana/e2e-selectors'; | ||||||
| import { locationService } from '@grafana/runtime'; | import { locationService } from '@grafana/runtime'; | ||||||
|  | @ -23,6 +23,11 @@ export const ui = { | ||||||
|     labelKey: (idx: number) => byTestId(`label-key-${idx}`), |     labelKey: (idx: number) => byTestId(`label-key-${idx}`), | ||||||
|     labelValue: (idx: number) => byTestId(`label-value-${idx}`), |     labelValue: (idx: number) => byTestId(`label-value-${idx}`), | ||||||
|     expr: byTestId('expr'), |     expr: byTestId('expr'), | ||||||
|  |     simplifiedRouting: { | ||||||
|  |       contactPointRouting: byRole('radio', { name: /select contact point/i }), | ||||||
|  |       contactPoint: byTestId('contact-point-picker'), | ||||||
|  |       routingOptions: byText(/muting, grouping and timings \(optional\)/i), | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   buttons: { |   buttons: { | ||||||
|     saveAndExit: byRole('button', { name: 'Save rule and exit' }), |     saveAndExit: byRole('button', { name: 'Save rule and exit' }), | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue