From 0a3e85a269ecaa9f378464016dfb0ba83f98a983 Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:50:07 +0000 Subject: [PATCH] [ResponseOps][NewRuleForm] Update functional tests to use new rule form for stack management (#198915) ## Summary Meta issue https://github.com/elastic/kibana/issues/196235 This PR updates existing e2e tests to use the new rule form instead of old rule flyout for `stack management > rules` ### Flaky test runner https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7488 https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7530 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../src/rule_form/create_rule_form.tsx | 1 + .../rule_form/rule_page/rule_page.test.tsx | 4 +- .../src/rule_form/rule_page/rule_page.tsx | 2 +- .../utils/get_initial_multi_consumer.ts | 20 + .../test/functional/services/ml/alerting.ts | 2 +- .../test/functional/services/rules/common.ts | 10 +- .../discover/search_source_alert.ts | 10 +- .../discover_ml_uptime/ml/alert_flyout.ts | 1 + .../alert_create_flyout.ts | 347 +++++++++--------- .../connectors/opsgenie.ts | 47 ++- .../triggers_actions_ui/connectors/slack.ts | 27 +- .../apps/triggers_actions_ui/details.ts | 150 ++------ .../rules_list/rules_list.ts | 2 +- .../functional_with_es_ssl/config.base.ts | 1 - .../page_objects/triggers_actions_ui_page.ts | 18 +- 15 files changed, 290 insertions(+), 352 deletions(-) diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx index 8bdadc69a6f1a..b0d95a7d5c2c9 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/create_rule_form.tsx @@ -195,6 +195,7 @@ export const CreateRuleForm = (props: CreateRuleFormProps) => { multiConsumerSelection, validConsumers, ruleType, + ruleTypes, }), }} > diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.test.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.test.tsx index 9523dad2a8a6f..710f046adb28a 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.test.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.test.tsx @@ -152,7 +152,7 @@ describe('rulePage', () => { render(); fireEvent.click(screen.getByTestId('rulePageFooterCancelButton')); - expect(screen.getByTestId('ruleFormCancelModal')).toBeInTheDocument(); + expect(screen.getByTestId('confirmRuleCloseModal')).toBeInTheDocument(); }); test('should not display discard changes modal id no changes are made in the form', () => { @@ -181,6 +181,6 @@ describe('rulePage', () => { render(); fireEvent.click(screen.getByTestId('rulePageFooterCancelButton')); - expect(screen.queryByTestId('ruleFormCancelModal')).not.toBeInTheDocument(); + expect(screen.queryByTestId('confirmRuleCloseModal')).not.toBeInTheDocument(); }); }); diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.tsx b/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.tsx index bdb2838bc9963..de15ccaca441c 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.tsx +++ b/packages/kbn-alerts-ui-shared/src/rule_form/rule_page/rule_page.tsx @@ -217,7 +217,7 @@ export const RulePage = (props: RulePageProps) => { setIsCancelModalOpen(false)} onConfirm={onCancel} - data-test-subj="ruleFormCancelModal" + data-test-subj="confirmRuleCloseModal" buttonColor="danger" defaultFocusedButton="confirm" title={RULE_FORM_CANCEL_MODAL_TITLE} diff --git a/packages/kbn-alerts-ui-shared/src/rule_form/utils/get_initial_multi_consumer.ts b/packages/kbn-alerts-ui-shared/src/rule_form/utils/get_initial_multi_consumer.ts index ee80bf46b99c8..0f4ffe41d67da 100644 --- a/packages/kbn-alerts-ui-shared/src/rule_form/utils/get_initial_multi_consumer.ts +++ b/packages/kbn-alerts-ui-shared/src/rule_form/utils/get_initial_multi_consumer.ts @@ -11,6 +11,7 @@ import { AlertConsumers, RuleCreationValidConsumer } from '@kbn/rule-data-utils' import { RuleTypeWithDescription } from '../../common/types'; import { MULTI_CONSUMER_RULE_TYPE_IDS } from '../constants'; import { FEATURE_NAME_MAP } from '../translations'; +import { getAuthorizedConsumers } from './get_authorized_consumers'; export const getValidatedMultiConsumer = ({ multiConsumerSelection, @@ -33,10 +34,12 @@ export const getInitialMultiConsumer = ({ multiConsumerSelection, validConsumers, ruleType, + ruleTypes, }: { multiConsumerSelection?: RuleCreationValidConsumer | null; validConsumers: RuleCreationValidConsumer[]; ruleType: RuleTypeWithDescription; + ruleTypes: RuleTypeWithDescription[]; }): RuleCreationValidConsumer | null => { // If rule type doesn't support multi-consumer or no valid consumers exists, // return nothing @@ -54,6 +57,23 @@ export const getInitialMultiConsumer = ({ return AlertConsumers.OBSERVABILITY; } + const selectedAvailableRuleType = ruleTypes.find((availableRuleType) => { + return availableRuleType.id === ruleType.id; + }); + + if (!selectedAvailableRuleType?.authorizedConsumers) { + return null; + } + + const authorizedConsumers = getAuthorizedConsumers({ + ruleType: selectedAvailableRuleType, + validConsumers, + }); + + if (authorizedConsumers.length === 1) { + return authorizedConsumers[0]; + } + // User passed in null explicitly, won't set initial consumer if (multiConsumerSelection === null) { return null; diff --git a/x-pack/test/functional/services/ml/alerting.ts b/x-pack/test/functional/services/ml/alerting.ts index 74c6eb735ea34..9a42c09e8829f 100644 --- a/x-pack/test/functional/services/ml/alerting.ts +++ b/x-pack/test/functional/services/ml/alerting.ts @@ -28,7 +28,7 @@ export function MachineLearningAlertingProvider( async selectAnomalyDetectionAlertType() { await retry.tryForTime(5000, async () => { await testSubjects.click('xpack.ml.anomaly_detection_alert-SelectOption'); - await testSubjects.existOrFail(`mlAnomalyAlertForm`, { timeout: 1000 }); + await testSubjects.existOrFail(`mlAnomalyAlertForm`); }); }, diff --git a/x-pack/test/functional/services/rules/common.ts b/x-pack/test/functional/services/rules/common.ts index 934fdefef10ed..fcc1bf26099c5 100644 --- a/x-pack/test/functional/services/rules/common.ts +++ b/x-pack/test/functional/services/rules/common.ts @@ -27,7 +27,7 @@ export function RulesCommonServiceProvider({ getService, getPageObject }: FtrPro }, async cancelRuleCreation() { - await testSubjects.click('cancelSaveRuleButton'); + await testSubjects.click('rulePageFooterCancelButton'); await testSubjects.existOrFail('confirmRuleCloseModal'); await testSubjects.click('confirmRuleCloseModal > confirmModalConfirmButton'); await testSubjects.missingOrFail('confirmRuleCloseModal'); @@ -43,8 +43,6 @@ export function RulesCommonServiceProvider({ getService, getPageObject }: FtrPro await browser.refresh(); await this.clickCreateAlertButton(); await testSubjects.click(`.index-threshold-SelectOption`); - await testSubjects.scrollIntoView('ruleNameInput'); - await testSubjects.setValue('ruleNameInput', alertName); await testSubjects.scrollIntoView('selectIndexExpression'); await testSubjects.click('selectIndexExpression'); await comboBox.set('thresholdIndexesComboBox', 'k'); @@ -55,9 +53,6 @@ export function RulesCommonServiceProvider({ getService, getPageObject }: FtrPro await fieldOptions[1].click(); }); await testSubjects.click('closePopover'); - // need this two out of popup clicks to close them - const nameInput = await testSubjects.find('ruleNameInput'); - await nameInput.click(); await testSubjects.click('whenExpression'); await testSubjects.click('whenExpressionSelect'); @@ -74,6 +69,9 @@ export function RulesCommonServiceProvider({ getService, getPageObject }: FtrPro const ofOptions = ofOptionsString.trim().split('\n'); expect(ofOptions.length > 0).to.be(true); await comboBox.set('availableFieldsOptionsComboBox', ofOptions[0]); + + await testSubjects.scrollIntoView('ruleDetailsNameInput'); + await testSubjects.setValue('ruleDetailsNameInput', alertName); }, }; } diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/search_source_alert.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/search_source_alert.ts index 8c176c61530b7..97d59de76ce4f 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/search_source_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/search_source_alert.ts @@ -470,7 +470,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('thresholdPopover'); await testSubjects.setValue('alertThresholdInput0', '1'); - await testSubjects.click('saveEditedRuleButton'); + await testSubjects.click('rulePageFooterSaveButton'); await PageObjects.header.waitUntilLoadingHasFinished(); await openAlertResults(RULE_NAME); @@ -622,8 +622,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.header.waitUntilLoadingHasFinished(); await retry.waitFor('rule name value is correct', async () => { - await testSubjects.setValue('ruleNameInput', newAlert); - const ruleName = await testSubjects.getAttribute('ruleNameInput', 'value'); + await testSubjects.setValue('ruleDetailsNameInput', newAlert); + const ruleName = await testSubjects.getAttribute('ruleDetailsNameInput', 'value'); return ruleName === newAlert; }); @@ -641,10 +641,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); await sourceDataViewOption.click(); - await testSubjects.click('saveRuleButton'); + await testSubjects.click('rulePageFooterSaveButton'); await retry.waitFor('confirmation modal', async () => { - return await testSubjects.exists('confirmModalConfirmButton'); + return await testSubjects.exists('rulePageConfirmCreateRule'); }); await testSubjects.click('confirmModalConfirmButton'); diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts index 58c72ef9d1a27..e76093c666ca1 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/alert_flyout.ts @@ -134,6 +134,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.setAlertName('ml-test-alert'); await pageObjects.triggersActionsUI.setAlertInterval(10, 's'); await pageObjects.triggersActionsUI.saveAlert(); + await ml.navigation.navigateToAlertsAndAction(); await pageObjects.triggersActionsUI.clickOnAlertInAlertsList('ml-test-alert'); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index 121bb753e434b..07e6aa841f8e2 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -47,6 +47,30 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); } + async function createWebhookConnector(connectorName: string) { + await pageObjects.common.navigateToApp('triggersActionsConnectors'); + await testSubjects.click('connectorsTab'); + + await testSubjects.click('createConnectorButton'); + await testSubjects.scrollIntoView('.webhook-card'); + await testSubjects.click('.webhook-card'); + + await testSubjects.setValue('nameInput', connectorName); + await testSubjects.setValue('webhookUrlText', 'https://test.test'); + await testSubjects.setValue('webhookUserInput', 'fakeuser'); + await testSubjects.setValue('webhookPasswordInput', 'fakepassword'); + + await retry.try(async () => { + await find.clickByCssSelector( + '[data-test-subj="create-connector-flyout-save-btn"]:not(disabled)' + ); + await testSubjects.click('create-connector-flyout-save-btn'); + }); + + const toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql(`Created '${connectorName}'`); + } + async function deleteConnectorByName(connectorName: string) { const { body: connectors } = await supertest.get(`/api/actions/connectors`).expect(200); const connector = connectors?.find((c: { name: string }) => c.name === connectorName); @@ -62,7 +86,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { async function defineEsQueryAlert(alertName: string) { await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.click(`.es-query-SelectOption`); - await testSubjects.setValue('ruleNameInput', alertName); + await testSubjects.setValue('ruleDetailsNameInput', alertName); await testSubjects.click('queryFormType_esQuery'); await testSubjects.click('selectIndexExpression'); await comboBox.set('thresholdIndexesComboBox', 'k'); @@ -74,20 +98,21 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await testSubjects.click('closePopover'); // need this two out of popup clicks to close them - const nameInput = await testSubjects.find('ruleNameInput'); + const nameInput = await testSubjects.find('ruleDetailsNameInput'); await nameInput.click(); } async function defineAPMErrorCountRule(ruleName: string) { await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.click(`apm.error_rate-SelectOption`); - await testSubjects.setValue('ruleNameInput', ruleName); + await testSubjects.setValue('ruleDetailsNameInput', ruleName); } async function defineAlwaysFiringAlert(alertName: string) { await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.click('test.always-firing-SelectOption'); - await testSubjects.setValue('ruleNameInput', alertName); + await testSubjects.scrollIntoView('ruleDetailsNameInput'); + await testSubjects.setValue('ruleDetailsNameInput', alertName); } async function discardNewRuleCreation() { @@ -95,12 +120,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { } // Failing: See https://github.com/elastic/kibana/issues/196153 - describe.skip('create alert', function () { + describe('create alert', function () { let apmSynthtraceEsClient: ApmSynthtraceEsClient; + const webhookConnectorName = 'webhook-test'; before(async () => { await esArchiver.load( 'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword' ); + + await createWebhookConnector(webhookConnectorName); + const version = (await apmSynthtraceKibanaClient.installApmPackage()).version; apmSynthtraceEsClient = await getApmSynthtraceEsClient({ client: esClient, @@ -137,10 +166,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); after(async () => { - await apmSynthtraceEsClient.clean(); + await apmSynthtraceEsClient?.clean(); await esArchiver.unload( 'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword' ); + + await deleteConnectorByName(webhookConnectorName); }); beforeEach(async () => { @@ -153,24 +184,25 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const ruleName = generateUniqueKey(); await rules.common.defineIndexThresholdAlert(ruleName); - // create webhook connector - await testSubjects.click('.webhook-alerting-ActionTypeSelectOption'); - await testSubjects.click('createActionConnectorButton-0'); - await testSubjects.setValue('nameInput', 'webhook-test'); - await testSubjects.setValue('webhookUrlText', 'https://test.test'); - await testSubjects.setValue('webhookUserInput', 'fakeuser'); - await testSubjects.setValue('webhookPasswordInput', 'fakepassword'); - - // save rule - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); + // add webhook connector 1 + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText(webhookConnectorName); await find.setValueByClass('kibanaCodeEditor', 'myUniqueKey'); - await testSubjects.click('saveRuleButton'); + + await testSubjects.click('rulePageFooterSaveButton'); // add new action and remove first one - await testSubjects.click('ruleSidebarEditAction'); - await testSubjects.click('.webhook-alerting-ActionTypeSelectOption'); + await testSubjects.click('openEditRuleFlyoutButton'); + + // add webhook connector 2 + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText(webhookConnectorName); + await find.setValueByClass('kibanaCodeEditor', 'myUniqueKey1'); + await find.clickByCssSelector( - '[data-test-subj="alertActionAccordion-0"] [aria-label="Delete"]' + '[data-test-subj="ruleActionsItem"] [data-test-subj="ruleActionsItemDeleteButton"]' ); // check that the removed action is the right one @@ -184,7 +216,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Additional cleanup step to prevent // FLAKY: https://github.com/elastic/kibana/issues/167443 // FLAKY: https://github.com/elastic/kibana/issues/167444 - await deleteConnectorByName('webhook-test'); }); it('should create an alert', async () => { @@ -198,29 +229,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.setValue('filterKuery', 'group: group-0'); expect(await filterKueryInput.elementHasClass('euiFieldSearch-isInvalid')).to.eql(false); - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); - await testSubjects.click('addNewActionConnectorButton-.slack'); - const slackConnectorName = generateUniqueKey(); - await testSubjects.setValue('nameInput', slackConnectorName); - await testSubjects.setValue('slackWebhookUrlInput', 'https://test.com'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); - const createdConnectorToastTitle = await toasts.getTitleAndDismiss(); - expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); - await testSubjects.click('notifyWhenSelect'); - await testSubjects.click('onThrottleInterval'); - await testSubjects.setValue('throttleInput', '10'); - - // Alerts search bar (conditional actions) - await testSubjects.click('alertsFilterQueryToggle'); - - await pageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.click('addFilter'); - await testSubjects.click('filterFieldSuggestionList'); - await comboBox.set('filterFieldSuggestionList', '_id'); - await comboBox.set('filterOperatorList', 'is not'); - await testSubjects.setValue('filterParams', 'fake-rule-id'); - await testSubjects.click('saveFilter'); - await testSubjects.setValue('queryInput', '_id: *'); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText('Slack#xyztest'); const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql( @@ -246,9 +257,29 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'test message {{alert.actionGroup}} some additional text {{rule.id}}' ); - await testSubjects.click('saveRuleButton'); + await find.clickByButtonText('Settings'); + await testSubjects.click('notifyWhenSelect'); + await testSubjects.click('onThrottleInterval'); + await testSubjects.setValue('throttleInput', '10'); + + // Alerts search bar (conditional actions) + await testSubjects.click('alertsFilterQueryToggle'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('addFilter'); + await testSubjects.click('filterFieldSuggestionList'); + await comboBox.set('filterFieldSuggestionList', '_id'); + await comboBox.set('filterOperatorList', 'is not'); + await testSubjects.setValue('filterParams', 'fake-rule-id'); + await testSubjects.click('saveFilter'); + await testSubjects.setValue('queryInput', '_id: *'); + + await testSubjects.click('rulePageFooterSaveButton'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${alertName}"`); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); await pageObjects.triggersActionsUI.searchAlerts(alertName); const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); const searchResultAfterSave = searchResultsAfterSave[0]; @@ -275,14 +306,35 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.setValue('filterKuery', 'group: group-0'); expect(await filterKueryInput.elementHasClass('euiFieldSearch-isInvalid')).to.eql(false); - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); - await testSubjects.click('addNewActionConnectorButton-.slack'); - const slackConnectorName = generateUniqueKey(); - await testSubjects.setValue('nameInput', slackConnectorName); - await testSubjects.setValue('slackWebhookUrlInput', 'https://test.com'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); - const createdConnectorToastTitle = await toasts.getTitleAndDismiss(); - expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText('Slack#xyztest'); + + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); + expect(await messageTextArea.getAttribute('value')).to.eql( + `Rule {{rule.name}} is active for group {{context.group}}: + +- Value: {{context.value}} +- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.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.setValue('messageVariablesSelectableSearch', 'rule.id'); + await testSubjects.click('variableMenuButton-rule.id'); + + expect(await messageTextArea.getAttribute('value')).to.eql( + 'test message {{alert.actionGroup}} some additional text {{rule.id}}' + ); + + await find.clickByButtonText('Settings'); await testSubjects.click('notifyWhenSelect'); await testSubjects.click('onThrottleInterval'); await testSubjects.setValue('throttleInput', '10'); @@ -314,32 +366,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('saveFilter'); await testSubjects.setValue('queryInput', '_id: *'); - const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); - expect(await messageTextArea.getAttribute('value')).to.eql( - `Rule {{rule.name}} is active for group {{context.group}}: - -- Value: {{context.value}} -- Conditions Met: {{context.conditions}} over {{rule.params.timeWindowSize}}{{rule.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.setValue('messageVariablesSelectableSearch', 'rule.id'); - 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('saveRuleButton'); + await testSubjects.click('rulePageFooterSaveButton'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${alertName}"`); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); await pageObjects.triggersActionsUI.searchAlerts(alertName); const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); const searchResultAfterSave = searchResultsAfterSave[0]; @@ -366,14 +398,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.setValue('filterKuery', 'group: group-0'); expect(await filterKueryInput.elementHasClass('euiFieldSearch-isInvalid')).to.eql(false); - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); - await testSubjects.click('addNewActionConnectorButton-.slack'); - const slackConnectorName = generateUniqueKey(); - await testSubjects.setValue('nameInput', slackConnectorName); - await testSubjects.setValue('slackWebhookUrlInput', 'https://test.com'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); - const createdConnectorToastTitle = await toasts.getTitleAndDismiss(); - expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText('Slack#xyztest'); + + await find.clickByButtonText('Settings'); await testSubjects.click('notifyWhenSelect'); await testSubjects.click('onThrottleInterval'); await testSubjects.setValue('throttleInput', '10'); @@ -384,19 +413,19 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const filter = `{ "bool": { - "filter": [{ "term": { "kibana.alert.rule.consumer": "*" } }] + "filter": [{ "term": { "kibana.alert.rule.name": "${alertName}" } }] } }`; - await filterBar.addDslFilter(filter, true); - - await testSubjects.click('saveRuleButton'); + await filterBar.addDslFilter(filter); + await testSubjects.click('rulePageFooterSaveButton'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${alertName}"`); - await testSubjects.click('editActionHoverButton'); + await testSubjects.click('openEditRuleFlyoutButton'); await pageObjects.header.waitUntilLoadingHasFinished(); + await find.clickByButtonText('Settings'); await testSubjects.scrollIntoView('globalQueryBar'); await filterBar.hasFilter('query', filter, true); @@ -410,37 +439,36 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const alertName = generateUniqueKey(); await defineAlwaysFiringAlert(alertName); - // create Slack connector and attach an action using it - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); - await testSubjects.click('addNewActionConnectorButton-.slack'); - const slackConnectorName = generateUniqueKey(); - await testSubjects.setValue('nameInput', slackConnectorName); - await testSubjects.setValue('slackWebhookUrlInput', 'https://test.com'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); - const createdConnectorToastTitle = await toasts.getTitleAndDismiss(); - expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText('Slack#xyztest'); + await testSubjects.setValue('messageTextArea', 'test message '); await ( await find.byCssSelector( - '[data-test-subj="alertActionAccordion-0"] [data-test-subj="messageTextArea"]' + '[data-test-subj="ruleActionsItem"] [data-test-subj="messageTextArea"]' ) ).type('some text '); + await find.clickByButtonText('Settings'); + await testSubjects.click('ruleActionsSettingsSelectActionGroup'); + await testSubjects.click('addNewActionConnectorActionGroup-recovered'); - await testSubjects.click('addAlertActionButton'); - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); - await testSubjects.setValue('messageTextArea', 'test message '); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText('Slack#xyztest'); + + const actionItems = await find.allByCssSelector('[data-test-subj="ruleActionsItem"]'); await ( - await find.byCssSelector( - '[data-test-subj="alertActionAccordion-1"] [data-test-subj="messageTextArea"]' - ) + await actionItems[1].findByCssSelector('[data-test-subj="messageTextArea"]') ).type('some text '); - await testSubjects.click('addNewActionConnectorActionGroup-1'); - await testSubjects.click('addNewActionConnectorActionGroup-1-option-other'); - - await testSubjects.click('saveRuleButton'); + await testSubjects.click('rulePageFooterSaveButton'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${alertName}"`); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); + await pageObjects.triggersActionsUI.searchAlerts(alertName); const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); const searchResultAfterSave = searchResultsAfterSave[0]; @@ -459,20 +487,24 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const alertName = generateUniqueKey(); await defineAlwaysFiringAlert(alertName); - await testSubjects.click('saveRuleButton'); - await testSubjects.existOrFail('confirmRuleSaveModal'); - await testSubjects.click('confirmRuleSaveModal > confirmModalCancelButton'); + await testSubjects.click('rulePageFooterSaveButton'); + await testSubjects.existOrFail('rulePageConfirmCreateRule'); + await testSubjects.click('rulePageConfirmCreateRule > confirmModalCancelButton'); await testSubjects.missingOrFail('confirmRuleSaveModal'); - await find.existsByCssSelector('[data-test-subj="saveRuleButton"]:not(disabled)'); + await find.existsByCssSelector('[data-test-subj="rulePageFooterSaveButton"]:not(disabled)'); - await testSubjects.click('saveRuleButton'); - await testSubjects.existOrFail('confirmRuleSaveModal'); - await testSubjects.click('confirmRuleSaveModal > confirmModalConfirmButton'); - await testSubjects.missingOrFail('confirmRuleSaveModal'); + await testSubjects.click('rulePageFooterSaveButton'); + await testSubjects.existOrFail('rulePageConfirmCreateRule'); + await testSubjects.click('rulePageConfirmCreateRule > confirmModalConfirmButton'); + await testSubjects.missingOrFail('rulePageConfirmCreateRule'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${alertName}"`); await new Promise((resolve) => setTimeout(resolve, 1000)); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); + await pageObjects.triggersActionsUI.searchAlerts(alertName); const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); const searchResultAfterSave = searchResultsAfterSave[0]; @@ -490,13 +522,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('should show discard confirmation before closing flyout without saving', async () => { await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.click(`.es-query-SelectOption`); - await testSubjects.click('cancelSaveRuleButton'); + await testSubjects.click('rulePageFooterCancelButton'); await testSubjects.missingOrFail('confirmRuleCloseModal'); await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.click(`.es-query-SelectOption`); - await testSubjects.setValue('ruleNameInput', 'alertName'); - await testSubjects.click('cancelSaveRuleButton'); + await testSubjects.setValue('ruleDetailsNameInput', 'alertName'); + await testSubjects.click('rulePageFooterCancelButton'); await testSubjects.existOrFail('confirmRuleCloseModal'); await testSubjects.click('confirmRuleCloseModal > confirmModalCancelButton'); await testSubjects.missingOrFail('confirmRuleCloseModal'); @@ -521,7 +553,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.missingOrFail('testQuerySuccess'); await testSubjects.existOrFail('testQueryError'); await testSubjects.setValue('queryJsonEditor', ''); - await discardNewRuleCreation(); + + await testSubjects.click('rulePageFooterCancelButton'); + + const confirmRuleCloseModalExists = await testSubjects.exists('confirmRuleCloseModal'); + if (confirmRuleCloseModalExists) { + await testSubjects.click('confirmRuleCloseModal > confirmModalConfirmButton'); + await testSubjects.missingOrFail('confirmRuleCloseModal'); + } }); // Related issue that this test is trying to prevent: @@ -554,65 +593,23 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('testQuerySuccess'); await testSubjects.missingOrFail('testQueryError'); - await discardNewRuleCreation(); - }); - - it('should not do a type override when adding a second action', async () => { - // create a new rule - const ruleName = generateUniqueKey(); - await rules.common.defineIndexThresholdAlert(ruleName); - - // add server log action - await testSubjects.click('.server-log-alerting-ActionTypeSelectOption'); - expect( - await find.existsByCssSelector( - '[data-test-subj="comboBoxSearchInput"][value="Serverlog#xyz"]' - ) - ).to.eql(true); - expect( - await find.existsByCssSelector( - '[data-test-subj="comboBoxSearchInput"][value="webhook-test"]' - ) - ).to.eql(false); - - // click on add new action - await testSubjects.click('addAlertActionButton'); - await find.existsByCssSelector('[data-test-subj="Serverlog#xyz"]'); - - // create webhook connector - await testSubjects.click('.webhook-alerting-ActionTypeSelectOption'); - await testSubjects.click('createActionConnectorButton-1'); - await testSubjects.setValue('nameInput', 'webhook-test'); - await testSubjects.setValue('webhookUrlText', 'https://test.test'); - await testSubjects.setValue('webhookUserInput', 'fakeuser'); - await testSubjects.setValue('webhookPasswordInput', 'fakepassword'); - await testSubjects.click('saveActionButtonModal'); - - // checking the new one first to avoid flakiness. If the value is checked before the new one is added - // it might return a false positive - expect( - await find.existsByCssSelector( - '[data-test-subj="comboBoxSearchInput"][value="webhook-test"]' - ) - ).to.eql(true); - // If it was overridden, the value would change to be empty - expect( - await find.existsByCssSelector( - '[data-test-subj="comboBoxSearchInput"][value="Serverlog#xyz"]' - ) - ).to.eql(true); + await testSubjects.click('rulePageFooterCancelButton'); - await deleteConnectorByName('webhook-test'); + const confirmRuleCloseModalExists = await testSubjects.exists('confirmRuleCloseModal'); + if (confirmRuleCloseModalExists) { + await testSubjects.click('confirmRuleCloseModal > confirmModalConfirmButton'); + await testSubjects.missingOrFail('confirmRuleCloseModal'); + } }); it('should add filter', async () => { const ruleName = generateUniqueKey(); await defineAlwaysFiringAlert(ruleName); - await testSubjects.click('saveRuleButton'); - await testSubjects.existOrFail('confirmRuleSaveModal'); - await testSubjects.click('confirmRuleSaveModal > confirmModalConfirmButton'); - await testSubjects.missingOrFail('confirmRuleSaveModal'); + await testSubjects.click('rulePageFooterSaveButton'); + await testSubjects.existOrFail('rulePageConfirmCreateRule'); + await testSubjects.click('rulePageConfirmCreateRule > confirmModalConfirmButton'); + await testSubjects.missingOrFail('rulePageConfirmCreateRule'); const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql(`Created rule "${ruleName}"`); @@ -625,7 +622,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { } }`; - await filterBar.addDslFilter(filter, true); + await filterBar.addDslFilter(filter); await filterBar.hasFilter('query', filter, true); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts index 6656103b6a89a..c4eb6a7dcd093 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts @@ -307,48 +307,58 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('should default to the create alert action', async () => { + await find.clickByButtonText('Message'); await testSubjects.existOrFail('messageInput'); expect(await testSubjects.getAttribute('aliasInput', 'value')).to.eql(defaultAlias); }); it('should default to the close alert action when setting the run when to recovered', async () => { - await testSubjects.click('addNewActionConnectorActionGroup-0'); - await testSubjects.click('addNewActionConnectorActionGroup-0-option-recovered'); + await find.clickByButtonText('Settings'); + await testSubjects.click('ruleActionsSettingsSelectActionGroup'); + await testSubjects.click('addNewActionConnectorActionGroup-recovered'); + await find.clickByButtonText('Message'); expect(await testSubjects.getAttribute('aliasInput', 'value')).to.eql(defaultAlias); await testSubjects.existOrFail('noteTextArea'); await testSubjects.missingOrFail('messageInput'); }); it('should not preserve the alias when switching run when to recover', async () => { + await find.clickByButtonText('Message'); await testSubjects.setValue('aliasInput', 'an alias'); - await testSubjects.click('addNewActionConnectorActionGroup-0'); - await testSubjects.click('addNewActionConnectorActionGroup-0-option-recovered'); - await testSubjects.missingOrFail('messageInput'); + await find.clickByButtonText('Settings'); + await testSubjects.click('ruleActionsSettingsSelectActionGroup'); + await testSubjects.click('addNewActionConnectorActionGroup-recovered'); + await find.clickByButtonText('Message'); + await testSubjects.missingOrFail('messageInput'); expect(await testSubjects.getAttribute('aliasInput', 'value')).to.be(defaultAlias); }); it('should not preserve the alias when switching run when to threshold met', async () => { - await testSubjects.click('addNewActionConnectorActionGroup-0'); - await testSubjects.click('addNewActionConnectorActionGroup-0-option-recovered'); - await testSubjects.missingOrFail('messageInput'); + await find.clickByButtonText('Settings'); + await testSubjects.click('ruleActionsSettingsSelectActionGroup'); + await testSubjects.click('addNewActionConnectorActionGroup-recovered'); + await find.clickByButtonText('Message'); + await testSubjects.missingOrFail('messageInput'); await testSubjects.setValue('aliasInput', 'an alias'); - await testSubjects.click('addNewActionConnectorActionGroup-0'); - await testSubjects.click('addNewActionConnectorActionGroup-0-option-threshold met'); - await testSubjects.exists('messageInput'); + await find.clickByButtonText('Settings'); + await testSubjects.click('ruleActionsSettingsSelectActionGroup'); + await testSubjects.click('addNewActionConnectorActionGroup-threshold met'); + + await find.clickByButtonText('Message'); + await testSubjects.exists('messageInput'); expect(await testSubjects.getAttribute('aliasInput', 'value')).to.be(defaultAlias); }); it('should show the message is required error when clicking the save button', async () => { - await testSubjects.click('saveRuleButton'); - const messageError = await find.byClassName('euiFormErrorText'); - - expect(await messageError.getVisibleText()).to.eql('Message is required.'); + expect( + await (await testSubjects.find('rulePageFooterSaveButton')).getAttribute('disabled') + ).to.be('true'); }); }); @@ -360,8 +370,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }; const selectOpsgenieConnectorInRuleAction = async (name: string) => { - await testSubjects.click('.opsgenie-alerting-ActionTypeSelectOption'); - await testSubjects.selectValue('comboBoxInput', name); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText(name); + + await find.clickByButtonText('Settings'); await rules.common.setNotifyThrottleInput(); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts index 026608ecf0e08..a7ea6aef95c8a 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts @@ -14,6 +14,7 @@ import { createSlackConnectorAndObjectRemover, getConnectorByName } from './util export default ({ getPageObjects, getService }: FtrProviderContext) => { const testSubjects = getService('testSubjects'); const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); + const find = getService('find'); const retry = getService('retry'); const supertest = getService('supertest'); const actions = getService('actions'); @@ -119,10 +120,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return response.body.data[0].id; }; - const selectSlackConnectorInRuleAction = async ({ connectorId }: { connectorId: string }) => { - await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); // "Slack" in connector list - await testSubjects.click('selectActionConnector-.slack-0'); - await testSubjects.click(`dropdown-connector-${connectorId}`); + const selectSlackConnectorInRuleAction = async ({ + connectorName, + }: { + connectorName: string; + }) => { + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); + await find.clickByButtonText(connectorName); }; before(async () => { @@ -149,9 +154,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const ruleName = await setupRule(); await selectSlackConnectorInRuleAction({ - connectorId: webhookAction.id, + connectorName: webhookConnectorName, }); - await testSubjects.click('saveRuleButton'); + await testSubjects.click('rulePageFooterSaveButton'); + const toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql(`Created rule "${ruleName}"`); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); await pageObjects.triggersActionsUI.searchAlerts(ruleName); const ruleId = await getRuleIdByName(ruleName); @@ -166,9 +176,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { tags: '', }, ]); - - const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql(`Created rule "${ruleName}"`); }); /* FUTURE ENGINEER @@ -179,7 +186,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it.skip('should save webapi type slack connectors', async () => { await setupRule(); await selectSlackConnectorInRuleAction({ - connectorId: webApiAction.id, + connectorName: webhookConnectorName, }); await testSubjects.click('saveRuleButton'); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 04a5d97017124..56150e5693a39 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -23,7 +23,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const retry = getService('retry'); const find = getService('find'); const supertest = getService('supertest'); - const comboBox = getService('comboBox'); const objectRemover = new ObjectRemover(supertest); const toasts = getService('toasts'); @@ -187,7 +186,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const editButton = await testSubjects.find('ruleIntervalToastEditButton'); await editButton.click(); - await testSubjects.click('cancelSaveEditedRuleButton'); + await testSubjects.click('rulePageFooterCancelButton'); }); it('should disable the rule', async () => { @@ -375,14 +374,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await editButton.click(); expect(await testSubjects.exists('hasActionsDisabled')).to.eql(false); - await testSubjects.setValue('ruleNameInput', updatedRuleName, { + await testSubjects.setValue('ruleDetailsNameInput', updatedRuleName, { clearWithKeyboard: true, }); - await find.clickByCssSelector('[data-test-subj="saveEditedRuleButton"]:not(disabled)'); + await find.clickByCssSelector('[data-test-subj="rulePageFooterSaveButton"]:not(disabled)'); const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql(`Updated '${updatedRuleName}'`); + expect(toastTitle).to.eql(`Updated "${updatedRuleName}"`); await retry.tryForTime(30 * 1000, async () => { const headingText = await pageObjects.ruleDetailsUI.getHeadingText(); @@ -407,18 +406,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const editButton = await testSubjects.find('openEditRuleFlyoutButton'); await editButton.click(); - await testSubjects.setValue('ruleNameInput', uuidv4(), { + await testSubjects.setValue('ruleDetailsNameInput', uuidv4(), { clearWithKeyboard: true, }); - await testSubjects.click('cancelSaveEditedRuleButton'); + await testSubjects.click('rulePageFooterCancelButton'); await testSubjects.existOrFail('confirmRuleCloseModal'); await testSubjects.click('confirmRuleCloseModal > confirmModalConfirmButton'); - await find.waitForDeletedByCssSelector('[data-test-subj="cancelSaveEditedRuleButton"]'); + await find.waitForDeletedByCssSelector('[data-test-subj="rulePageFooterCancelButton"]'); await editButton.click(); - const nameInputAfterCancel = await testSubjects.find('ruleNameInput'); + const nameInputAfterCancel = await testSubjects.find('ruleDetailsNameInput'); const textAfterCancel = await nameInputAfterCancel.getAttribute('value'); expect(textAfterCancel).to.eql(updatedRuleName); }); @@ -482,127 +481,26 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 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); + const headerText = await find.byCssSelector('[data-test-subj="ruleActionsItem"] h2'); - expect(await testSubjects.exists('selectActionConnector-.slack-0')).to.eql(true); - // click the super selector the reveal the options - await testSubjects.click('selectActionConnector-.slack-0'); - // click the available option (my-slack1 is a preconfigured connector created before this test runs) - 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}}' }, - frequency: { - summary: false, - notify_when: RuleNotifyWhen.THROTTLE, - throttle: '1m', - }, - }, - { - group: 'other', - id: connector.id, - params: { level: 'info', message: ' {{context.message}}' }, - frequency: { - summary: false, - notify_when: RuleNotifyWhen.THROTTLE, - throttle: '1m', - }, - }, - ], - }); - - // refresh to see alert - await browser.refresh(); - await pageObjects.header.waitUntilLoadingHasFinished(); - - // verify content - await testSubjects.existOrFail('rulesList'); - - // delete connector - await pageObjects.common.navigateToApp('triggersActionsConnectors'); - 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 toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql('Deleted 1 connector'); - - // Wait to ensure the table is finished loading - await pageObjects.triggersActionsUI.tableFinishedLoading(); - - // click on first rule - await pageObjects.common.navigateToApp('triggersActions'); - await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(alert.name); - - const editButton = await testSubjects.find('openEditRuleFlyoutButton'); - 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 () => { - // At times we find the driver controlling the ComboBox in tests - // can select the wrong item, this ensures we always select the correct index - 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 headerText.getVisibleText()).to.eql('Unable to find connector'); - expect(await testSubjects.exists('addNewActionConnectorActionGroup-0')).to.eql(true); - expect(await testSubjects.exists('addNewActionConnectorActionGroup-1')).to.eql(true); + await testSubjects.click('ruleActionsAddActionButton'); + await testSubjects.existOrFail('ruleActionsConnectorsModal'); - // delete connector - await pageObjects.common.navigateToApp('triggersActions'); - // refresh to see alert - await browser.refresh(); - await pageObjects.header.waitUntilLoadingHasFinished(); + // click the available option (my-slack1 is a preconfigured connector created before this test runs) + await find.clickByButtonText('Slack#xyztest'); - // verify content - await testSubjects.existOrFail('rulesList'); + const ruleActionItems = await testSubjects.findAll('ruleActionsItem'); + expect(ruleActionItems.length).to.eql(2); - await pageObjects.common.navigateToApp('triggersActionsConnectors'); - await pageObjects.triggersActionsUI.searchConnectors('new connector'); - await testSubjects.click('deleteConnector'); - await testSubjects.existOrFail('deleteIdsConfirmation'); - await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); - await testSubjects.missingOrFail('deleteIdsConfirmation'); + expect(await ruleActionItems[0].getVisibleText()).to.contain('Slack'); + expect(await ruleActionItems[1].getVisibleText()).to.contain('Slack'); }); }); - describe('Edit rule with legacy rule-level notify values', function () { + // bug with legacy notify_when values https://github.com/elastic/kibana/issues/199494 + describe.skip('Edit rule with legacy rule-level notify values', function () { const testRunUuid = uuidv4(); afterEach(async () => { @@ -643,20 +541,22 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const editButton = await testSubjects.find('openEditRuleFlyoutButton'); await editButton.click(); + + await find.clickByButtonText('Settings'); const notifyWhenSelect = await testSubjects.find('notifyWhenSelect'); expect(await notifyWhenSelect.getVisibleText()).to.eql('On custom action intervals'); const throttleInput = await testSubjects.find('throttleInput'); const throttleUnitInput = await testSubjects.find('throttleUnitInput'); expect(await throttleInput.getAttribute('value')).to.be('2'); expect(await throttleUnitInput.getAttribute('value')).to.be('d'); - await testSubjects.setValue('ruleNameInput', updatedRuleName, { + await testSubjects.setValue('ruleDetailsNameInput', updatedRuleName, { clearWithKeyboard: true, }); - await find.clickByCssSelector('[data-test-subj="saveEditedRuleButton"]:not(disabled)'); + await find.clickByCssSelector('[data-test-subj="rulePageFooterSaveButton"]:not(disabled)'); const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql(`Updated '${updatedRuleName}'`); + expect(toastTitle).to.eql(`Updated '${rule.name}'`); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts index 70f9d672b94a1..a9de637cd691a 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts @@ -449,7 +449,7 @@ export default ({ getPageObjects, getPageObject, getService }: FtrProviderContex const infoIcon = await testSubjects.find('ruleInterval-config-icon-0'); await infoIcon.click(); - await testSubjects.click('cancelSaveEditedRuleButton'); + await testSubjects.click('rulePageFooterCancelButton'); }); it('should delete all selection', async () => { diff --git a/x-pack/test/functional_with_es_ssl/config.base.ts b/x-pack/test/functional_with_es_ssl/config.base.ts index 2abf100f2823f..bcc6e00b9a979 100644 --- a/x-pack/test/functional_with_es_ssl/config.base.ts +++ b/x-pack/test/functional_with_es_ssl/config.base.ts @@ -85,7 +85,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { 'stackAlertsPage', 'ruleTagFilter', 'ruleStatusFilter', - 'isUsingRuleCreateFlyout', ])}`, `--xpack.alerting.rules.minimumScheduleInterval.value="5s"`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, diff --git a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts index 1880400dc37c5..e56b9f71f169d 100644 --- a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts +++ b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts @@ -166,31 +166,33 @@ export function TriggersActionsPageProvider({ getService }: FtrProviderContext) await rules.common.clickCreateAlertButton(); }, async setAlertName(value: string) { - await testSubjects.setValue('ruleNameInput', value); + await testSubjects.setValue('ruleDetailsNameInput', value); await this.assertAlertName(value); }, async assertAlertName(expectedValue: string) { - const actualValue = await testSubjects.getAttribute('ruleNameInput', 'value'); + const actualValue = await testSubjects.getAttribute('ruleDetailsNameInput', 'value'); expect(actualValue).to.eql(expectedValue); }, async setAlertInterval(value: number, unit?: 's' | 'm' | 'h' | 'd') { - await testSubjects.setValue('intervalInput', value.toString()); + await testSubjects.setValue('ruleScheduleNumberInput', value.toString()); if (unit) { - await testSubjects.selectValue('intervalInputUnit', unit); + await testSubjects.selectValue('ruleScheduleUnitInput', unit); } await this.assertAlertInterval(value, unit); }, async assertAlertInterval(expectedValue: number, expectedUnit?: 's' | 'm' | 'h' | 'd') { - const actualValue = await testSubjects.getAttribute('intervalInput', 'value'); + const actualValue = await testSubjects.getAttribute('ruleScheduleNumberInput', 'value'); expect(actualValue).to.eql(expectedValue); if (expectedUnit) { - const actualUnitValue = await testSubjects.getAttribute('intervalInputUnit', 'value'); + const actualUnitValue = await testSubjects.getAttribute('ruleScheduleUnitInput', 'value'); expect(actualUnitValue).to.eql(expectedUnit); } }, async saveAlert() { - await testSubjects.click('saveRuleButton'); - const isConfirmationModalVisible = await testSubjects.isDisplayed('confirmRuleSaveModal'); + await testSubjects.click('rulePageFooterSaveButton'); + const isConfirmationModalVisible = await testSubjects.isDisplayed( + 'rulePageConfirmCreateRule' + ); expect(isConfirmationModalVisible).to.eql(true, 'Expect confirmation modal to be visible'); await testSubjects.click('confirmModalConfirmButton'); },