import expect from '@kbn/expect' ; import uuid from 'uuid' ; import { omit , mapValues , range , flatten } from 'lodash' ; import moment from 'moment' ; import { FtrProviderContext } from '../../ftr_provider_context' ; import { ObjectRemover } from '../../lib/object_remover' ; import { alwaysFiringAlertType } from '../../fixtures/plugins/alerts/server/plugin' ; import { getTestAlertData , getTestActionData } from '../../lib/get_test_data' ; export default ( { getPageObjects , getService } ) => { const testSubjects = getService ( 'testSubjects' ) ; const pageObjects = getPageObjects ( [ 'common' , 'triggersActionsUI' , 'header' , 'ruleDetailsUI' ] ) ; const browser = getService ( 'browser' ) ; const log = getService ( 'log' ) ; const retry = getService ( 'retry' ) ; const find = getService ( 'find' ) ; const supertest = getService ( 'supertest' ) ; const comboBox = getService ( 'comboBox' ) ; const objectRemover = new ObjectRemover ( supertest ) ; async function createConnectorManualCleanup ( overwrites = { } ) { const { body : createdConnector } = await supertest . post ( `/api/actions/connector` ) . set ( 'kbn-xsrf' , 'foo' ) . send ( getTestActionData ( overwrites ) ) . expect ( 200 ) ; return createdConnector ; } async function createConnector ( overwrites = { } ) { const createdConnector = await createConnectorManualCleanup ( overwrites ) ; objectRemover . add ( createdConnector . id , 'action' , 'actions' ) ; return createdConnector ; } async function createRule ( overwrites = { } ) { const { body : createdRule } = await supertest . post ( `/api/alerting/rule` ) . set ( 'kbn-xsrf' , 'foo' ) . send ( getTestAlertData ( overwrites ) ) . expect ( 200 ) ; objectRemover . add ( createdRule . id , 'alert' , 'alerts' ) ; return createdRule ; } async function createAlwaysFiringRule ( overwrites = { } ) { const { body : createdRule } = await supertest . post ( `/api/alerting/rule` ) . set ( 'kbn-xsrf' , 'foo' ) . send ( getTestAlertData ( { rule_type_id : 'test.always-firing' , ... overwrites , } ) ) . expect ( 200 ) ; objectRemover . add ( createdRule . id , 'alert' , 'alerts' ) ; return createdRule ; } async function createConnectors ( testRunUuid ) { return await Promise . all ( [ createConnector ( { name : `slack-${ testRunUuid }-${ 0 }` } ) , createConnector ( { name : `slack-${ testRunUuid }-${ 1 }` } ) , ] ) ; } async function createRuleWithActionsAndParams ( testRunUuid , params = { } ) { const connectors = await createConnectors ( testRunUuid ) ; return await createAlwaysFiringRule ( { name : `test-rule-${ testRunUuid }` , actions : connectors . map ( ( connector ) => ( { id : connector . id , group : 'default' , params : { message : 'from alert 1s' , level : 'warn' , } , } ) ) , params , } ) ; } async function getAlertSummary ( ruleId ) { const { body : summary } = await supertest . get ( `/internal/alerting/rule/${ encodeURIComponent ( ruleId ) }/_alert_summary` ) . expect ( 200 ) ; return summary ; } async function muteAlert ( ruleId , alertId ) { const { body : response } = await supertest . post ( `/api/alerting/rule/${ encodeURIComponent ( ruleId ) }/alert/${ encodeURIComponent ( alertId ) }/_mute` ) . set ( 'kbn-xsrf' , 'foo' ) . expect ( 204 ) ; return response ; } describe ( 'Rule Details' , function ( ) { describe ( 'Header' , function ( ) { const testRunUuid = uuid . v4 ( ) ; before ( async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; const rule = await createRuleWithActionsAndParams ( testRunUuid ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; } ) ; after ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; it ( 'renders the rule details' , async ( ) => { const headingText = await pageObjects . ruleDetailsUI . getHeadingText ( ) ; expect ( headingText . includes ( `test-rule-${ testRunUuid }` ) ) . to . be ( true ) ; const ruleType = await pageObjects . ruleDetailsUI . getRuleType ( ) ; expect ( ruleType ) . to . be ( `Always Firing` ) ; const { connectorType } = await pageObjects . ruleDetailsUI . getActionsLabels ( ) ; expect ( connectorType ) . to . be ( `Slack` ) ; } ) ; it ( 'should disable the rule' , async ( ) => { const enableSwitch = await testSubjects . find ( 'enableSwitch' ) ; const isChecked = await enableSwitch . getAttribute ( 'aria-checked' ) ; expect ( isChecked ) . to . eql ( 'true' ) ; await enableSwitch . click ( ) ; const disableSwitchAfterDisabling = await testSubjects . find ( 'enableSwitch' ) ; const isCheckedAfterDisabling = await disableSwitchAfterDisabling . getAttribute ( 'aria-checked' ) ; expect ( isCheckedAfterDisabling ) . to . eql ( 'false' ) ; } ) ; it ( 'shouldnt allow you to mute a disabled rule' , async ( ) => { const disabledEnableSwitch = await testSubjects . find ( 'enableSwitch' ) ; expect ( await disabledEnableSwitch . getAttribute ( 'aria-checked' ) ) . to . eql ( 'false' ) ; const muteSwitch = await testSubjects . find ( 'muteSwitch' ) ; expect ( await muteSwitch . getAttribute ( 'aria-checked' ) ) . to . eql ( 'false' ) ; await muteSwitch . click ( ) ; const muteSwitchAfterTryingToMute = await testSubjects . find ( 'muteSwitch' ) ; const isDisabledMuteAfterDisabling = await muteSwitchAfterTryingToMute . getAttribute ( 'aria-checked' ) ; expect ( isDisabledMuteAfterDisabling ) . to . eql ( 'false' ) ; } ) ; it ( 'should reenable a disabled the rule' , async ( ) => { const enableSwitch = await testSubjects . find ( 'enableSwitch' ) ; const isChecked = await enableSwitch . getAttribute ( 'aria-checked' ) ; expect ( isChecked ) . to . eql ( 'false' ) ; await enableSwitch . click ( ) ; const disableSwitchAfterReenabling = await testSubjects . find ( 'enableSwitch' ) ; const isCheckedAfterDisabling = await disableSwitchAfterReenabling . getAttribute ( 'aria-checked' ) ; expect ( isCheckedAfterDisabling ) . to . eql ( 'true' ) ; } ) ; it ( 'should mute the rule' , async ( ) => { const muteSwitch = await testSubjects . find ( 'muteSwitch' ) ; const isChecked = await muteSwitch . getAttribute ( 'aria-checked' ) ; expect ( isChecked ) . to . eql ( 'false' ) ; await muteSwitch . click ( ) ; const muteSwitchAfterDisabling = await testSubjects . find ( 'muteSwitch' ) ; const isCheckedAfterDisabling = await muteSwitchAfterDisabling . getAttribute ( 'aria-checked' ) ; expect ( isCheckedAfterDisabling ) . to . eql ( 'true' ) ; } ) ; it ( 'should unmute the rule' , async ( ) => { const muteSwitch = await testSubjects . find ( 'muteSwitch' ) ; const isChecked = await muteSwitch . getAttribute ( 'aria-checked' ) ; expect ( isChecked ) . to . eql ( 'true' ) ; await muteSwitch . click ( ) ; const muteSwitchAfterUnmuting = await testSubjects . find ( 'muteSwitch' ) ; const isCheckedAfterDisabling = await muteSwitchAfterUnmuting . getAttribute ( 'aria-checked' ) ; expect ( isCheckedAfterDisabling ) . to . eql ( 'false' ) ; } ) ; } ) ; describe ( 'Edit rule button' , function ( ) { const ruleName = uuid . v4 ( ) ; const updatedRuleName = `Changed Rule Name ${ ruleName }` ; before ( async ( ) => { await createAlwaysFiringRule ( { name : ruleName , rule_type_id : '.index-threshold' , params : { aggType : 'count' , termSize : 5 , thresholdComparator : '>' , timeWindowSize : 5 , timeWindowUnit : 'm' , groupBy : 'all' , threshold : [ 1000 , 5000 ] , index : '.kibana_1' , timeField : 'alert' , } , actions : [ { group : 'threshold met' , id : 'my-server-log' , params : { level : 'info' , message : ' {{context.message}}' } , } , ] , } ) ; } ) ; after ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; it ( 'should open edit rule flyout' , async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( ruleName ) ; const editButton = await testSubjects . find ( 'openEditAlertFlyoutButton' ) ; await editButton . click ( ) ; expect ( await testSubjects . exists ( 'hasActionsDisabled' ) ) . to . eql ( false ) ; await testSubjects . setValue ( 'alertNameInput' , updatedRuleName , { clearWithKeyboard : true , } ) ; await find . clickByCssSelector ( '[data-test-subj="saveEditedAlertButton"]:not(disabled)' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( `Updated '${ updatedRuleName }'` ) ; const headingText = await pageObjects . ruleDetailsUI . getHeadingText ( ) ; expect ( headingText . includes ( updatedRuleName ) ) . to . be ( true ) ; } ) ; it ( 'should reset rule when canceling an edit' , async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( updatedRuleName ) ; const editButton = await testSubjects . find ( 'openEditAlertFlyoutButton' ) ; await editButton . click ( ) ; await testSubjects . setValue ( 'alertNameInput' , uuid . v4 ( ) , { clearWithKeyboard : true , } ) ; await testSubjects . click ( 'cancelSaveEditedAlertButton' ) ; await testSubjects . existOrFail ( 'confirmAlertCloseModal' ) ; await testSubjects . click ( 'confirmAlertCloseModal > confirmModalConfirmButton' ) ; await find . waitForDeletedByCssSelector ( '[data-test-subj="cancelSaveEditedAlertButton"]' ) ; await editButton . click ( ) ; const nameInputAfterCancel = await testSubjects . find ( 'alertNameInput' ) ; const textAfterCancel = await nameInputAfterCancel . getAttribute ( 'value' ) ; expect ( textAfterCancel ) . to . eql ( updatedRuleName ) ; } ) ; } ) ; describe ( 'Edit rule with deleted connector' , function ( ) { const testRunUuid = uuid . v4 ( ) ; afterEach ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; it ( 'should show and update deleted connectors when there are existing connectors of the same type' , async ( ) => { const connector = await createConnectorManualCleanup ( { name : `slack-${ testRunUuid }-${ 0 }` , } ) ; await pageObjects . common . navigateToApp ( 'triggersActions' ) ; const rule = await createAlwaysFiringRule ( { name : testRunUuid , actions : [ { group : 'default' , id : connector . id , params : { level : 'info' , message : ' {{context.message}}' } , } , ] , } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . changeTabs ( 'connectorsTab' ) ; await pageObjects . triggersActionsUI . searchConnectors ( connector . name ) ; await testSubjects . click ( 'deleteConnector' ) ; await testSubjects . existOrFail ( 'deleteIdsConfirmation' ) ; await testSubjects . click ( 'deleteIdsConfirmation > confirmModalConfirmButton' ) ; await testSubjects . missingOrFail ( 'deleteIdsConfirmation' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( 'Deleted 1 connector' ) ; await pageObjects . triggersActionsUI . changeTabs ( 'rulesTab' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; const editButton = await testSubjects . find ( 'openEditAlertFlyoutButton' ) ; await editButton . click ( ) ; expect ( await testSubjects . exists ( 'hasActionsDisabled' ) ) . to . eql ( false ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-0' ) ) . to . eql ( false ) ; expect ( await testSubjects . exists ( 'alertActionAccordion-0' ) ) . to . eql ( true ) ; expect ( await testSubjects . exists ( 'selectActionConnector-.slack-0' ) ) . to . eql ( true ) ; await testSubjects . click ( 'selectActionConnector-.slack-0' ) ; await testSubjects . click ( 'dropdown-connector-my-slack1' ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-0' ) ) . to . eql ( true ) ; } ) ; it ( 'should show and update deleted connectors when there are no existing connectors of the same type' , async ( ) => { const connector = await createConnectorManualCleanup ( { name : `index-${ testRunUuid }-${ 0 }` , connector_type_id : '.index' , config : { index : `index-${ testRunUuid }-${ 0 }` , } , secrets : { } , } ) ; await pageObjects . common . navigateToApp ( 'triggersActions' ) ; const alert = await createAlwaysFiringRule ( { name : testRunUuid , actions : [ { group : 'default' , id : connector . id , params : { level : 'info' , message : ' {{context.message}}' } , } , { group : 'other' , id : connector . id , params : { level : 'info' , message : ' {{context.message}}' } , } , ] , } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . changeTabs ( 'connectorsTab' ) ; await pageObjects . triggersActionsUI . searchConnectors ( connector . name ) ; await testSubjects . click ( 'deleteConnector' ) ; await testSubjects . existOrFail ( 'deleteIdsConfirmation' ) ; await testSubjects . click ( 'deleteIdsConfirmation > confirmModalConfirmButton' ) ; await testSubjects . missingOrFail ( 'deleteIdsConfirmation' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( 'Deleted 1 connector' ) ; await pageObjects . triggersActionsUI . changeTabs ( 'rulesTab' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( alert . name ) ; const editButton = await testSubjects . find ( 'openEditAlertFlyoutButton' ) ; await editButton . click ( ) ; expect ( await testSubjects . exists ( 'hasActionsDisabled' ) ) . to . eql ( false ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-0' ) ) . to . eql ( false ) ; expect ( await testSubjects . exists ( 'alertActionAccordion-0' ) ) . to . eql ( true ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-1' ) ) . to . eql ( false ) ; expect ( await testSubjects . exists ( 'alertActionAccordion-1' ) ) . to . eql ( true ) ; await testSubjects . click ( 'createActionConnectorButton-0' ) ; await testSubjects . existOrFail ( 'connectorAddModal' ) ; await testSubjects . setValue ( 'nameInput' , 'new connector' ) ; await retry . try ( async ( ) => { await comboBox . set ( 'connectorIndexesComboBox' , 'test-index' ) ; expect ( await comboBox . isOptionSelected ( await testSubjects . find ( 'connectorIndexesComboBox' ) , 'test-index' ) ) . to . be ( true ) ; } ) ; await testSubjects . click ( 'connectorAddModal > saveActionButtonModal' ) ; await testSubjects . missingOrFail ( 'deleteIdsConfirmation' ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-0' ) ) . to . eql ( true ) ; expect ( await testSubjects . exists ( 'addNewActionConnectorActionGroup-1' ) ) . to . eql ( true ) ; } ) ; } ) ; describe ( 'View In App' , function ( ) { const ruleName = uuid . v4 ( ) ; beforeEach ( async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; } ) ; after ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; it ( 'renders the rule details view in app button' , async ( ) => { const rule = await createRule ( { name : ruleName , consumer : 'alerting_fixture' , } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; expect ( await pageObjects . ruleDetailsUI . isViewInAppEnabled ( ) ) . to . be ( true ) ; await pageObjects . ruleDetailsUI . clickViewInApp ( ) ; expect ( await pageObjects . ruleDetailsUI . getNoOpAppTitle ( ) ) . to . be ( `View Rule ${ rule . id }` ) ; } ) ; it ( 'renders a disabled rule details view in app button' , async ( ) => { const rule = await createAlwaysFiringRule ( { name : `test-rule-disabled-nav` , } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; expect ( await pageObjects . ruleDetailsUI . isViewInAppDisabled ( ) ) . to . be ( true ) ; } ) ; } ) ; describe ( 'Alerts' , function ( ) { const testRunUuid = uuid . v4 ( ) ; let rule ; before ( async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; const alerts = [ { id : 'us-central' } , { id : 'us-east' } , { id : 'us-west' } ] ; rule = await createRuleWithActionsAndParams ( testRunUuid , { instances : alerts , } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; await retry . try ( async ( ) => { const { alerts : alertInstances } = await getAlertSummary ( rule . id ) ; expect ( Object . keys ( alertInstances ) . length ) . to . eql ( alerts . length ) ; } ) ; } ) ; after ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; it ( 'renders the active alerts' , async ( ) => { await browser . refresh ( ) ; const { actionGroups } = alwaysFiringAlertType ; await testSubjects . existOrFail ( 'alertsList' ) ; const actionGroupNameFromId = ( actionGroupId ) => actionGroups . find ( ( actionGroup ) => actionGroup . id === actionGroupId ) ?. name ; const summary = await getAlertSummary ( rule . id ) ; const dateOnAllAlertsFromApiResponse = mapValues ( summary . alerts , ( a ) => a . activeStartDate ) ; const actionGroupNameOnAllInstancesFromApiResponse = mapValues ( summary . alerts , ( a ) => { const name = actionGroupNameFromId ( a . actionGroupId ) ; return name ? ` (${ name })` : '' ; } ) ; log . debug ( `API RESULT: ${ Object . entries ( dateOnAllAlertsFromApiResponse ) . map ( ( [ id , date ] ) => `${ id }: ${ moment ( date ) . utc ( ) }` ) . join ( ', ' ) }` ) ; const alertsList = await pageObjects . ruleDetailsUI . getAlertsList ( ) ; expect ( alertsList . map ( ( a ) => omit ( a , 'duration' ) ) ) . to . eql ( [ { alert : 'us-central' , status : `Active${ actionGroupNameOnAllInstancesFromApiResponse [ 'us-central' ] }` , start : moment ( dateOnAllAlertsFromApiResponse [ 'us-central' ] ) . utc ( ) . format ( 'D MMM YYYY @ HH:mm:ss' ) , } , { alert : 'us-east' , status : `Active${ actionGroupNameOnAllInstancesFromApiResponse [ 'us-east' ] }` , start : moment ( dateOnAllAlertsFromApiResponse [ 'us-east' ] ) . utc ( ) . format ( 'D MMM YYYY @ HH:mm:ss' ) , } , { alert : 'us-west' , status : `Active${ actionGroupNameOnAllInstancesFromApiResponse [ 'us-west' ] }` , start : moment ( dateOnAllAlertsFromApiResponse [ 'us-west' ] ) . utc ( ) . format ( 'D MMM YYYY @ HH:mm:ss' ) , } , ] ) ; const durationEpoch = moment ( await pageObjects . ruleDetailsUI . getAlertDurationEpoch ( ) ) . utc ( ) ; log . debug ( `DURATION EPOCH is: ${ durationEpoch }]` ) ; const durationFromInstanceInApiUntilPageLoad = mapValues ( dateOnAllAlertsFromApiResponse , ( date ) => { const durationFromApiResuiltToEpoch = moment . duration ( durationEpoch . diff ( moment ( date ) . utc ( ) ) ) ; return moment . duration ( { hours : durationFromApiResuiltToEpoch . hours ( ) , minutes : durationFromApiResuiltToEpoch . minutes ( ) , seconds : durationFromApiResuiltToEpoch . seconds ( ) , } ) ; } ) ; alertsList . map ( ( a ) => ( { id : a . alert , duration : moment . duration ( a . duration ) , } ) ) . forEach ( ( { id , duration : durationAsItAppearsOnList } ) => { log . debug ( `DURATION of ${ id } [From UI: ${ durationAsItAppearsOnList . as ( 'seconds' ) } seconds] [From API: ${ durationFromInstanceInApiUntilPageLoad [ id ] . as ( 'seconds' ) } seconds]` ) ; expect ( durationFromInstanceInApiUntilPageLoad [ id ] . as ( 'seconds' ) ) . to . equal ( durationAsItAppearsOnList . as ( 'seconds' ) ) ; } ) ; } ) ; it ( 'renders the muted inactive alerts' , async ( ) => { await muteAlert ( rule . id , 'eu/east' ) ; await browser . refresh ( ) ; const alertsList = await pageObjects . ruleDetailsUI . getAlertsList ( ) ; expect ( alertsList . filter ( ( a ) => a . alert === 'eu/east' ) ) . to . eql ( [ { alert : 'eu/east' , status : 'Recovered' , start : '' , duration : '' , } , ] ) ; } ) ; it ( 'allows the user to mute a specific alert' , async ( ) => { await testSubjects . existOrFail ( 'alertsList' ) ; log . debug ( `Ensuring us-central is not muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'us-central' , false ) ; log . debug ( `Muting us-central` ) ; await pageObjects . ruleDetailsUI . clickAlertMuteButton ( 'us-central' ) ; log . debug ( `Ensuring us-central is muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'us-central' , true ) ; } ) ; it ( 'allows the user to unmute a specific alert' , async ( ) => { await testSubjects . existOrFail ( 'alertsList' ) ; log . debug ( `Ensuring us-east is not muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'us-east' , false ) ; log . debug ( `Muting us-east` ) ; await pageObjects . ruleDetailsUI . clickAlertMuteButton ( 'us-east' ) ; log . debug ( `Ensuring us-east is muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'us-east' , true ) ; log . debug ( `Unmuting us-east` ) ; await pageObjects . ruleDetailsUI . clickAlertMuteButton ( 'us-east' ) ; log . debug ( `Ensuring us-east is not muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'us-east' , false ) ; } ) ; it ( 'allows the user unmute an inactive alert' , async ( ) => { log . debug ( `Ensuring eu/east is muted` ) ; await pageObjects . ruleDetailsUI . ensureAlertMuteState ( 'eu/east' , true ) ; log . debug ( `Unmuting eu/east` ) ; await pageObjects . ruleDetailsUI . clickAlertMuteButton ( 'eu/east' ) ; log . debug ( `Ensuring eu/east is removed from list` ) ; await pageObjects . ruleDetailsUI . ensureAlertExistence ( 'eu/east' , false ) ; } ) ; } ) ; describe ( 'Alert Pagination' , function ( ) { const testRunUuid = uuid . v4 ( ) ; let rule ; before ( async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; const alerts = flatten ( range ( 10 ) . map ( ( index ) => [ { id : `us-central-${ index }` } , { id : `us-east-${ index }` } , { id : `us-west-${ index }` } , ] ) ) ; rule = await createRuleWithActionsAndParams ( testRunUuid , { instances : alerts , } ) ; await retry . try ( async ( ) => { const { alerts : alertInstances } = await getAlertSummary ( rule . id ) ; expect ( Object . keys ( alertInstances ) . length ) . to . eql ( alerts . length ) ; } ) ; await browser . refresh ( ) ; await pageObjects . header . waitUntilLoadingHasFinished ( ) ; await testSubjects . existOrFail ( 'alertsList' ) ; await pageObjects . triggersActionsUI . clickOnAlertInAlertsList ( rule . name ) ; } ) ; after ( async ( ) => { await objectRemover . removeAll ( ) ; } ) ; const PAGE_SIZE = 10 ; it ( 'renders the first page' , async ( ) => { await testSubjects . existOrFail ( 'alertsList' ) ; const { alerts : alertInstances } = await getAlertSummary ( rule . id ) ; const items = await pageObjects . ruleDetailsUI . getAlertsList ( ) ; expect ( items . length ) . to . eql ( PAGE_SIZE ) ; const [ firstItem ] = items ; expect ( firstItem . alert ) . to . eql ( Object . keys ( alertInstances ) [ 0 ] ) ; } ) ; it ( 'navigates to the next page' , async ( ) => { await testSubjects . existOrFail ( 'alertsList' ) ; const { alerts : alertInstances } = await getAlertSummary ( rule . id ) ; await pageObjects . ruleDetailsUI . clickPaginationNextPage ( ) ; await retry . try ( async ( ) => { const [ firstItem ] = await pageObjects . ruleDetailsUI . getAlertsList ( ) ; expect ( firstItem . alert ) . to . eql ( Object . keys ( alertInstances ) [ PAGE_SIZE ] ) ; } ) ; } ) ; } ) ; } ) ; } ;