@ -1,11 +1,13 @@
import { render , screen , userEvent , waitFor , within } from 'test/test-utils' ;
import { render , screen , waitFor , within } from 'test/test-utils' ;
import { byRole , byTestId , byText } from 'testing-library-selector' ;
import { setAlertmanagerConfig } from 'app/features/alerting/unified/mocks/server/entities/alertmanagers' ;
import { testWithFeatureToggles } from 'app/features/alerting/unified/test/test-utils' ;
import { AccessControlAction } from 'app/types/accessControl' ;
import { MatcherOperator } from '../../../../../../plugins/datasource/alertmanager/types' ;
import { Labels } from '../../../../../../types/unified-alerting-dto' ;
import { mockApi , setupMswServer } from '../../../mockApi' ;
import { getMockConfig , setupMswServer } from '../../../mockApi' ;
import { grantUserPermissions , mockAlertQuery } from '../../../mocks' ;
import { mockPreviewApiResponse } from '../../../mocks/grafanaRulerApi' ;
import { Folder } from '../../../types/rule-form' ;
@ -36,7 +38,7 @@ const ui = {
route : byTestId ( 'matching-policy-route' ) ,
routeButton : byRole ( 'button' , { name : /Expand policy route/ } ) ,
routeMatchingInstances : byTestId ( 'route-matching-instance' ) ,
loadingIndicator : byText ( /Loading/ ) ,
loadingIndicator : byText ( /Loading routing preview /i ) ,
previewButton : byRole ( 'button' , { name : /preview routing/i } ) ,
grafanaAlertManagerLabel : byText ( /alertmanager:grafana/i ) ,
otherAlertManagerLabel : byText ( /alertmanager:other_am/i ) ,
@ -62,52 +64,33 @@ const grafanaAlertManagerDataSource: AlertManagerDataSource = {
hasConfigurationAPI : true ,
} ;
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
. withReceiver ( 'email' )
. addRoute ( ( rb ) = > rb . withReceiver ( 'slack' ) . addMatcher ( 'tomato' , MatcherOperator . equal , 'red' ) )
. addRoute ( ( rb ) = > rb . withReceiver ( 'opsgenie' ) . addMatcher ( 'team' , MatcherOperator . equal , 'operations' ) )
)
. addReceivers ( ( b ) = > b . withName ( 'email' ) . addEmailConfig ( ( eb ) = > eb . withTo ( 'test@example.com' ) ) )
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
function mockOneAlertManager() {
getAlertManagerDataSourcesByPermissionAndConfigMock . mockReturnValue ( [ grafanaAlertManagerDataSource ] ) ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
. withReceiver ( 'email' )
. addRoute ( ( rb ) = > rb . withReceiver ( 'slack' ) . addMatcher ( 'tomato' , MatcherOperator . equal , 'red' ) )
. addRoute ( ( rb ) = > rb . withReceiver ( 'opsgenie' ) . addMatcher ( 'team' , MatcherOperator . equal , 'operations' ) )
)
. addReceivers ( ( b ) = > b . withName ( 'email' ) . addEmailConfig ( ( eb ) = > eb . withTo ( 'test@example.com' ) ) )
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
}
function mockTwoAlertManagers() {
getAlertManagerDataSourcesByPermissionAndConfigMock . mockReturnValue ( [
{ name : 'OTHER_AM' , imgUrl : '' , hasConfigurationAPI : true } ,
grafanaAlertManagerDataSource ,
{ name : 'OTHER_AM' , imgUrl : '' , hasConfigurationAPI : true } ,
] ) ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
. withReceiver ( 'email' )
. addRoute ( ( rb ) = > rb . withReceiver ( 'slack' ) . addMatcher ( 'tomato' , MatcherOperator . equal , 'red' ) )
. addRoute ( ( rb ) = > rb . withReceiver ( 'opsgenie' ) . addMatcher ( 'team' , MatcherOperator . equal , 'operations' ) )
)
. addReceivers ( ( b ) = > b . withName ( 'email' ) . addEmailConfig ( ( eb ) = > eb . withTo ( 'test@example.com' ) ) )
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
mockApi ( server ) . getAlertmanagerConfig ( 'OTHER_AM' , ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
. withReceiver ( 'email' )
. addRoute ( ( rb ) = > rb . withReceiver ( 'slack' ) . addMatcher ( 'tomato' , MatcherOperator . equal , 'red' ) )
. addRoute ( ( rb ) = > rb . withReceiver ( 'opsgenie' ) . addMatcher ( 'team' , MatcherOperator . equal , 'operations' ) )
)
. addReceivers ( ( b ) = > b . withName ( 'email' ) . addEmailConfig ( ( eb ) = > eb . withTo ( 'test@example.com' ) ) )
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
setAlertmanagerConfig ( 'OTHER_AM' , mockConfig ) ;
}
function mockHasEditPermission ( enabled : boolean ) {
@ -131,14 +114,22 @@ const folder: Folder = {
title : 'title' ,
} ;
describe ( 'NotificationPreview' , ( ) = > {
describe . each ( [
// k8s API enabled
true ,
// k8s API disabled
false ,
] ) ( 'NotificationPreview with alertingApiServer=%p' , ( apiServerEnabled ) = > {
apiServerEnabled ? testWithFeatureToggles ( [ 'alertingApiServer' ] ) : testWithFeatureToggles ( [ ] ) ;
it ( 'should render notification preview without alert manager label, when having only one alert manager configured to receive alerts' , async ( ) = > {
mockOneAlertManager ( ) ;
mockPreviewApiResponse ( server , [ { labels : [ { tomato : 'red' , avocate : 'green' } ] } ] ) ;
render ( < NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / > ) ;
const { user } = render (
< NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / >
) ;
await userEvent . click ( ui . previewButton . get ( ) ) ;
await user . click ( ui . previewButton . get ( ) ) ;
await waitFor ( ( ) = > {
expect ( ui . loadingIndicator . query ( ) ) . not . toBeInTheDocument ( ) ;
} ) ;
@ -160,23 +151,18 @@ describe('NotificationPreview', () => {
mockTwoAlertManagers ( ) ;
mockPreviewApiResponse ( server , [ { labels : [ { tomato : 'red' , avocate : 'green' } ] } ] ) ;
render ( < NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / > ) ;
await waitFor ( ( ) = > {
expect ( ui . loadingIndicator . query ( ) ) . not . toBeInTheDocument ( ) ;
} ) ;
const { user } = render (
< NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / >
) ;
await userEvent . click ( ui . previewButton . get ( ) ) ;
await waitFor ( ( ) = > {
expect ( ui . loadingIndicator . query ( ) ) . not . toBeInTheDocument ( ) ;
} ) ;
await user . click ( await ui . previewButton . find ( ) ) ;
// we expect the alert manager label to be present as there is more than one alert manager configured to receive alerts
await waitFor ( ( ) = > {
expect ( ui . grafanaAlertManagerLabel . query ( ) ) . toBeInTheDocument ( ) ;
} ) ;
expect ( ui . otherAlertManagerLabel . query ( ) ) . toBeInTheDocument ( ) ;
expect ( await ui . grafanaAlertManagerLabel . find ( ) ) . toBeInTheDocument ( ) ;
expect ( await ui . otherAlertManagerLabel . find ( ) ) . toBeInTheDocument ( ) ;
const matchingPoliciesElements = await ui . route . findAll ( ) ;
const matchingPoliciesElements = ui . route . queryAll ( ) ;
expect ( matchingPoliciesElements ) . toHaveLength ( 2 ) ;
expect ( matchingPoliciesElements [ 0 ] ) . toHaveTextContent ( /tomato = red/ ) ;
expect ( matchingPoliciesElements [ 1 ] ) . toHaveTextContent ( /tomato = red/ ) ;
@ -187,13 +173,15 @@ describe('NotificationPreview', () => {
mockPreviewApiResponse ( server , [ { labels : [ { tomato : 'red' , avocate : 'green' } ] } ] ) ;
mockHasEditPermission ( true ) ;
render ( < NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / > ) ;
const { user } = render (
< NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / >
) ;
await waitFor ( ( ) = > {
expect ( ui . loadingIndicator . query ( ) ) . not . toBeInTheDocument ( ) ;
} ) ;
await userEvent . click ( ui . previewButton . get ( ) ) ;
await userEvent . click ( await ui . seeDetails . find ( ) ) ;
await user . click ( ui . previewButton . get ( ) ) ;
await user . click ( await ui . seeDetails . find ( ) ) ;
expect ( ui . details . title . query ( ) ) . toBeInTheDocument ( ) ;
//we expect seeing the default policy
expect ( screen . getByText ( /default policy/i ) ) . toBeInTheDocument ( ) ;
@ -209,13 +197,15 @@ describe('NotificationPreview', () => {
mockPreviewApiResponse ( server , [ { labels : [ { tomato : 'red' , avocate : 'green' } ] } ] ) ;
mockHasEditPermission ( false ) ;
render ( < NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / > ) ;
const { user } = render (
< NotificationPreview alertQueries = { [ alertQuery ] } customLabels = { [ ] } condition = "A" folder = { folder } / >
) ;
await waitFor ( ( ) = > {
expect ( ui . loadingIndicator . query ( ) ) . not . toBeInTheDocument ( ) ;
} ) ;
await userEvent . click ( ui . previewButton . get ( ) ) ;
await userEvent . click ( await ui . seeDetails . find ( ) ) ;
await user . click ( ui . previewButton . get ( ) ) ;
await user . click ( await ui . seeDetails . find ( ) ) ;
expect ( ui . details . title . query ( ) ) . toBeInTheDocument ( ) ;
//we expect seeing the default policy
expect ( screen . getByText ( /default policy/i ) ) . toBeInTheDocument ( ) ;
@ -234,7 +224,7 @@ describe('NotificationPreviewByAlertmanager', () => {
{ job : 'prometheus' , severity : 'warning' } ,
] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
@ -246,10 +236,9 @@ describe('NotificationPreviewByAlertmanager', () => {
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
const user = userEvent . setup ( ) ;
render (
const { user } = render (
< NotificationPreviewByAlertManager
alertManagerSource = { grafanaAlertManagerDataSource }
potentialInstances = { potentialInstances }
@ -285,7 +274,7 @@ describe('NotificationPreviewByAlertmanager', () => {
{ job : 'prometheus' , severity : 'warning' } ,
] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
@ -300,10 +289,9 @@ describe('NotificationPreviewByAlertmanager', () => {
. addReceivers ( ( b ) = > b . withName ( 'slack' ) )
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
const user = userEvent . setup ( ) ;
render (
const { user } = render (
< NotificationPreviewByAlertManager
alertManagerSource = { grafanaAlertManagerDataSource }
potentialInstances = { potentialInstances }
@ -339,7 +327,7 @@ describe('NotificationPreviewByAlertmanager', () => {
{ job : 'prometheus' , severity : 'warning' } ,
] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. withRoute ( ( routeBuilder ) = >
routeBuilder
@ -355,9 +343,9 @@ describe('NotificationPreviewByAlertmanager', () => {
. addReceivers ( ( b ) = > b . withName ( 'opsgenie' ) )
) ;
const user = userEvent . setup ( ) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
render (
const { user } = render (
< NotificationPreviewByAlertManager
alertManagerSource = { grafanaAlertManagerDataSource }
potentialInstances = { potentialInstances }
@ -392,7 +380,7 @@ describe('NotificationPreviewByAlertmanager', () => {
it ( 'does not match regex in middle of the word as alertmanager will anchor when queried via API' , async ( ) = > {
const potentialInstances : Labels [ ] = [ { regexfield : 'foobarfoo' } ] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. addReceivers ( ( b ) = > b . withName ( 'email' ) )
. withRoute ( ( routeBuilder ) = >
@ -402,6 +390,8 @@ describe('NotificationPreviewByAlertmanager', () => {
)
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
render (
< NotificationPreviewByAlertManager
alertManagerSource = { grafanaAlertManagerDataSource }
@ -417,7 +407,7 @@ describe('NotificationPreviewByAlertmanager', () => {
it ( 'matches regex at the start of the word' , async ( ) = > {
const potentialInstances : Labels [ ] = [ { regexfield : 'baaaaaaah' } ] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. addReceivers ( ( b ) = > b . withName ( 'email' ) )
. withRoute ( ( routeBuilder ) = >
@ -426,6 +416,7 @@ describe('NotificationPreviewByAlertmanager', () => {
. addRoute ( ( rb ) = > rb . withReceiver ( 'email' ) . addMatcher ( 'regexfield' , MatcherOperator . regex , 'ba.*h' ) )
)
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
render (
< NotificationPreviewByAlertManager
@ -441,7 +432,7 @@ describe('NotificationPreviewByAlertmanager', () => {
it ( 'handles negated regex correctly' , async ( ) = > {
const potentialInstances : Labels [ ] = [ { regexfield : 'thing' } ] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. addReceivers ( ( b ) = > b . withName ( 'email' ) )
. withRoute ( ( routeBuilder ) = >
@ -450,6 +441,7 @@ describe('NotificationPreviewByAlertmanager', () => {
. addRoute ( ( rb ) = > rb . withReceiver ( 'email' ) . addMatcher ( 'regexfield' , MatcherOperator . notRegex , 'thing' ) )
)
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
render (
< NotificationPreviewByAlertManager
@ -466,7 +458,7 @@ describe('NotificationPreviewByAlertmanager', () => {
it ( 'matches regex with flags' , async ( ) = > {
const potentialInstances : Labels [ ] = [ { regexfield : 'baaaaaaah' } ] ;
mockApi ( server ) . getAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , ( amConfigBuilder ) = >
const mockConfig = getMockConfig ( ( amConfigBuilder ) = >
amConfigBuilder
. addReceivers ( ( b ) = > b . withName ( 'email' ) )
. withRoute ( ( routeBuilder ) = >
@ -475,6 +467,7 @@ describe('NotificationPreviewByAlertmanager', () => {
. addRoute ( ( rb ) = > rb . withReceiver ( 'email' ) . addMatcher ( 'regexfield' , MatcherOperator . regex , '(?i)BA.*h' ) )
)
) ;
setAlertmanagerConfig ( GRAFANA_RULES_SOURCE_NAME , mockConfig ) ;
render (
< NotificationPreviewByAlertManager