import expect from '@kbn/expect' ; import { asyncForEach } from '@kbn/std' ; import { omit } from 'lodash' ; import { FtrProviderContext } from '../../ftr_provider_context' ; import { generateUniqueKey } from '../../lib/get_test_data' ; export default ( { getPageObjects , getService } ) => { const testSubjects = getService ( 'testSubjects' ) ; const pageObjects = getPageObjects ( [ 'common' , 'triggersActionsUI' , 'header' ] ) ; const supertest = getService ( 'supertest' ) ; const find = getService ( 'find' ) ; const retry = getService ( 'retry' ) ; const comboBox = getService ( 'comboBox' ) ; const browser = getService ( 'browser' ) ; async function getAlertsByName ( name ) { const { body : { data : alerts } , } = await supertest . get ( `/api/alerting/rules/_find?search=${ name }&search_fields=name` ) . expect ( 200 ) ; return alerts ; } async function deleteAlerts ( alertIds ) { await asyncForEach ( alertIds , async ( alertId ) => { await supertest . delete ( `/api/alerting/rule/${ alertId }` ) . set ( 'kbn-xsrf' , 'foo' ) . expect ( 204 , '' ) ; } ) ; } async function defineEsQueryAlert ( alertName ) { await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . setValue ( 'alertNameInput' , alertName ) ; await testSubjects . click ( `.es-query-SelectOption` ) ; await testSubjects . click ( 'selectIndexExpression' ) ; const indexComboBox = await find . byCssSelector ( '#indexSelectSearchBox' ) ; await indexComboBox . click ( ) ; await indexComboBox . type ( 'k' ) ; const filterSelectItem = await find . byCssSelector ( `.euiFilterSelectItem` ) ; await filterSelectItem . click ( ) ; await testSubjects . click ( 'thresholdAlertTimeFieldSelect' ) ; await retry . try ( async ( ) => { const fieldOptions = await find . allByCssSelector ( '#thresholdTimeField option' ) ; expect ( fieldOptions [ 1 ] ) . not . to . be ( undefined ) ; await fieldOptions [ 1 ] . click ( ) ; } ) ; await testSubjects . click ( 'closePopover' ) ; const nameInput = await testSubjects . find ( 'alertNameInput' ) ; await nameInput . click ( ) ; } async function defineIndexThresholdAlert ( alertName ) { await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . setValue ( 'alertNameInput' , alertName ) ; await testSubjects . click ( `.index-threshold-SelectOption` ) ; await testSubjects . click ( 'selectIndexExpression' ) ; const indexComboBox = await find . byCssSelector ( '#indexSelectSearchBox' ) ; await indexComboBox . click ( ) ; await indexComboBox . type ( 'k' ) ; const filterSelectItem = await find . byCssSelector ( `.euiFilterSelectItem` ) ; await filterSelectItem . click ( ) ; await testSubjects . click ( 'thresholdAlertTimeFieldSelect' ) ; await retry . try ( async ( ) => { const fieldOptions = await find . allByCssSelector ( '#thresholdTimeField option' ) ; expect ( fieldOptions [ 1 ] ) . not . to . be ( undefined ) ; await fieldOptions [ 1 ] . click ( ) ; } ) ; await testSubjects . click ( 'closePopover' ) ; const nameInput = await testSubjects . find ( 'alertNameInput' ) ; await nameInput . click ( ) ; await testSubjects . click ( 'whenExpression' ) ; await testSubjects . click ( 'whenExpressionSelect' ) ; await retry . try ( async ( ) => { const aggTypeOptions = await find . allByCssSelector ( '#aggTypeField option' ) ; expect ( aggTypeOptions [ 1 ] ) . not . to . be ( undefined ) ; await aggTypeOptions [ 1 ] . click ( ) ; } ) ; await testSubjects . click ( 'ofExpressionPopover' ) ; const ofComboBox = await find . byCssSelector ( '#ofField' ) ; await ofComboBox . click ( ) ; const ofOptionsString = await comboBox . getOptionsList ( 'availablefieldsOptionsComboBox' ) ; const ofOptions = ofOptionsString . trim ( ) . split ( '\n' ) ; expect ( ofOptions . length > 0 ) . to . be ( true ) ; await comboBox . set ( 'availablefieldsOptionsComboBox' , ofOptions [ 0 ] ) ; } async function defineAlwaysFiringAlert ( alertName ) { await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . setValue ( 'alertNameInput' , alertName ) ; await testSubjects . click ( 'test.always-firing-SelectOption' ) ; } describe . skip ( 'create alert' , function ( ) { before ( async ( ) => { await pageObjects . common . navigateToApp ( 'triggersActions' ) ; await testSubjects . click ( 'rulesTab' ) ; } ) ; it ( 'should create an alert' , async ( ) => { const alertName = generateUniqueKey ( ) ; await defineIndexThresholdAlert ( alertName ) ; await testSubjects . click ( 'notifyWhenSelect' ) ; await testSubjects . click ( 'onThrottleInterval' ) ; await testSubjects . setValue ( 'throttleInput' , '10' ) ; await testSubjects . click ( '.slack-ActionTypeSelectOption' ) ; await testSubjects . click ( 'addNewActionConnectorButton-.slack' ) ; const slackConnectorName = generateUniqueKey ( ) ; await testSubjects . setValue ( 'nameInput' , slackConnectorName ) ; await testSubjects . setValue ( 'slackWebhookUrlInput' , 'https://test' ) ; await find . clickByCssSelector ( '[data-test-subj="saveActionButtonModal"]:not(disabled)' ) ; const createdConnectorToastTitle = await pageObjects . common . closeToast ( ) ; expect ( createdConnectorToastTitle ) . to . eql ( `Created '${ slackConnectorName }'` ) ; const messageTextArea = await find . byCssSelector ( '[data-test-subj="messageTextArea"]' ) ; expect ( await messageTextArea . getAttribute ( 'value' ) ) . to . eql ( `alert '{{alertName}}' is active for group '{{context.group}}':

- Value: {{context.value}}
- Conditions Met: {{context.conditions}} over {{params.timeWindowSize}}{{params.timeWindowUnit}}
- Timestamp: {{context.date}}` ) ; await testSubjects . setValue ( 'messageTextArea' , 'test message ' ) ; await testSubjects . click ( 'messageAddVariableButton' ) ; await testSubjects . click ( 'variableMenuButton-alert.actionGroup' ) ; expect ( await messageTextArea . getAttribute ( 'value' ) ) . to . eql ( 'test message {{alert.actionGroup}}' ) ; await messageTextArea . type ( ' some additional text ' ) ; await testSubjects . click ( 'messageAddVariableButton' ) ; await testSubjects . click ( 'variableMenuButton-rule.id' ) ; expect ( await messageTextArea . getAttribute ( 'value' ) ) . to . eql ( 'test message {{alert.actionGroup}} some additional text {{rule.id}}' ) ; await testSubjects . click ( 'saveAlertButton' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( `Created rule "${ alertName }"` ) ; await pageObjects . triggersActionsUI . searchAlerts ( alertName ) ; const searchResultsAfterSave = await pageObjects . triggersActionsUI . getAlertsList ( ) ; const searchResultAfterSave = searchResultsAfterSave [ 0 ] ; expect ( omit ( searchResultAfterSave , 'duration' ) ) . to . eql ( { name : `${ alertName }Index threshold` , tags : '' , interval : '1 min' , } ) ; expect ( searchResultAfterSave . duration ) . to . match ( /\d{2}:\d{2}:\d{2}.\d{3}/ ) ; const alertsToDelete = await getAlertsByName ( alertName ) ; await deleteAlerts ( alertsToDelete . map ( ( alertItem ) => alertItem . id ) ) ; } ) ; it ( 'should create an alert with actions in multiple groups' , async ( ) => { const alertName = generateUniqueKey ( ) ; await defineAlwaysFiringAlert ( alertName ) ; await testSubjects . click ( '.slack-ActionTypeSelectOption' ) ; await testSubjects . click ( 'addNewActionConnectorButton-.slack' ) ; const slackConnectorName = generateUniqueKey ( ) ; await testSubjects . setValue ( 'nameInput' , slackConnectorName ) ; await testSubjects . setValue ( 'slackWebhookUrlInput' , 'https://test' ) ; await find . clickByCssSelector ( '[data-test-subj="saveActionButtonModal"]:not(disabled)' ) ; const createdConnectorToastTitle = await pageObjects . common . closeToast ( ) ; expect ( createdConnectorToastTitle ) . to . eql ( `Created '${ slackConnectorName }'` ) ; await testSubjects . setValue ( 'messageTextArea' , 'test message ' ) ; await ( await find . byCssSelector ( '[data-test-subj="alertActionAccordion-0"] [data-test-subj="messageTextArea"]' ) ) . type ( 'some text ' ) ; await testSubjects . click ( 'addAlertActionButton' ) ; await testSubjects . click ( '.slack-ActionTypeSelectOption' ) ; await testSubjects . setValue ( 'messageTextArea' , 'test message ' ) ; await ( await find . byCssSelector ( '[data-test-subj="alertActionAccordion-1"] [data-test-subj="messageTextArea"]' ) ) . type ( 'some text ' ) ; await testSubjects . click ( 'addNewActionConnectorActionGroup-1' ) ; await testSubjects . click ( 'addNewActionConnectorActionGroup-1-option-other' ) ; await testSubjects . click ( 'saveAlertButton' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( `Created rule "${ alertName }"` ) ; await pageObjects . triggersActionsUI . searchAlerts ( alertName ) ; const searchResultsAfterSave = await pageObjects . triggersActionsUI . getAlertsList ( ) ; const searchResultAfterSave = searchResultsAfterSave [ 0 ] ; expect ( omit ( searchResultAfterSave , 'duration' ) ) . to . eql ( { name : `${ alertName }Always Firing` , tags : '' , interval : '1 min' , } ) ; const alertsToDelete = await getAlertsByName ( alertName ) ; await deleteAlerts ( alertsToDelete . map ( ( alertItem ) => alertItem . id ) ) ; } ) ; it ( 'should show save confirmation before creating alert with no actions' , async ( ) => { const alertName = generateUniqueKey ( ) ; await defineAlwaysFiringAlert ( alertName ) ; await testSubjects . click ( 'saveAlertButton' ) ; await testSubjects . existOrFail ( 'confirmAlertSaveModal' ) ; await testSubjects . click ( 'confirmAlertSaveModal > confirmModalCancelButton' ) ; await testSubjects . missingOrFail ( 'confirmAlertSaveModal' ) ; await find . existsByCssSelector ( '[data-test-subj="saveAlertButton"]:not(disabled)' ) ; await testSubjects . click ( 'saveAlertButton' ) ; await testSubjects . existOrFail ( 'confirmAlertSaveModal' ) ; await testSubjects . click ( 'confirmAlertSaveModal > confirmModalConfirmButton' ) ; await testSubjects . missingOrFail ( 'confirmAlertSaveModal' ) ; const toastTitle = await pageObjects . common . closeToast ( ) ; expect ( toastTitle ) . to . eql ( `Created rule "${ alertName }"` ) ; await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ; await pageObjects . triggersActionsUI . searchAlerts ( alertName ) ; const searchResultsAfterSave = await pageObjects . triggersActionsUI . getAlertsList ( ) ; const searchResultAfterSave = searchResultsAfterSave [ 0 ] ; expect ( omit ( searchResultAfterSave , 'duration' ) ) . to . eql ( { name : `${ alertName }Always Firing` , tags : '' , interval : '1 min' , } ) ; const alertsToDelete = await getAlertsByName ( alertName ) ; await deleteAlerts ( alertsToDelete . map ( ( alertItem ) => alertItem . id ) ) ; } ) ; it ( 'should show discard confirmation before closing flyout without saving' , async ( ) => { await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . click ( 'cancelSaveAlertButton' ) ; await testSubjects . missingOrFail ( 'confirmAlertCloseModal' ) ; await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . setValue ( 'intervalInput' , '10' ) ; await testSubjects . click ( 'cancelSaveAlertButton' ) ; await testSubjects . existOrFail ( 'confirmAlertCloseModal' ) ; await testSubjects . click ( 'confirmAlertCloseModal > confirmModalCancelButton' ) ; await testSubjects . missingOrFail ( 'confirmAlertCloseModal' ) ; } ) ; it ( 'should successfully test valid es_query alert' , async ( ) => { const alertName = generateUniqueKey ( ) ; await defineEsQueryAlert ( alertName ) ; await testSubjects . setValue ( 'queryJsonEditor' , '{"query":{"match_all":{}}}' , { clearWithKeyboard : true , } ) ; await testSubjects . click ( 'testQuery' ) ; await testSubjects . existOrFail ( 'testQuerySuccess' ) ; await testSubjects . missingOrFail ( 'testQueryError' ) ; await testSubjects . click ( 'cancelSaveAlertButton' ) ; await testSubjects . existOrFail ( 'confirmAlertCloseModal' ) ; await testSubjects . click ( 'confirmAlertCloseModal > confirmModalConfirmButton' ) ; } ) ; it ( 'should show error when es_query is invalid' , async ( ) => { const alertName = generateUniqueKey ( ) ; await defineEsQueryAlert ( alertName ) ; await testSubjects . setValue ( 'queryJsonEditor' , '{"query":{"foo":{}}}' , { clearWithKeyboard : true , } ) ; await testSubjects . click ( 'testQuery' ) ; await testSubjects . missingOrFail ( 'testQuerySuccess' ) ; await testSubjects . existOrFail ( 'testQueryError' ) ; } ) ; it ( 'should show all rule types on click euiFormControlLayoutClearButton' , async ( ) => { await pageObjects . triggersActionsUI . clickCreateAlertButton ( ) ; await testSubjects . setValue ( 'alertNameInput' , 'alertName' ) ; const ruleTypeSearchBox = await find . byCssSelector ( '[data-test-subj="alertSearchField"]' ) ; await ruleTypeSearchBox . type ( 'notexisting rule type' ) ; await ruleTypeSearchBox . pressKeys ( browser . keys . ENTER ) ; const ruleTypes = await find . allByCssSelector ( '.triggersActionsUI__alertTypeNodeHeading' ) ; expect ( ruleTypes ) . to . have . length ( 0 ) ; const searchClearButton = await find . byCssSelector ( '.euiFormControlLayoutClearButton' ) ; await searchClearButton . click ( ) ; const ruleTypesClearFilter = await find . allByCssSelector ( '.triggersActionsUI__alertTypeNodeHeading' ) ; expect ( ruleTypesClearFilter . length ) . to . above ( 0 ) ; } ) ; } ) ; } ;