From 22aa3119499d8828edc99f45980cd00ef792f57e Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Wed, 18 Sep 2024 03:56:58 -0400 Subject: [PATCH] [Observability] add custom threshold functional test (#184602) Closes #175301 ## Summary Resolves https://github.com/orgs/elastic/projects/1375/views/1?pane=issue&itemId=50879015 To run ``` cd x-pack && node ../scripts/functional_tests_server --config=test/observability_functional/with_rac_write.config.ts or node scripts/functional_tests_server.js --config x-pack/test/observability_functional/with_rac_write.config.ts ``` In a different terminal ``` node ../scripts/functional_test_runner --config=test/observability_functional/with_rac_write.config.ts --grep "Custom threshold rule" or node scripts/functional_test_runner --config=x-pack/test/observability_functional/with_rac_write.config.ts --grep "Custom threshold rule" ``` --------- Co-authored-by: Maryam Saeidi (cherry picked from commit 0241cf690c631d4865b9c412240ab49357646a26) --- .../custom_equation/metric_row_with_agg.tsx | 3 +- .../components/expression_row.tsx | 2 +- .../components/closable_popover_title.tsx | 9 +- .../expression_items/threshold.test.tsx | 15 +- .../common/expression_items/threshold.tsx | 7 +- .../services/observability/alerts/common.ts | 67 +++++ .../observability/alerts/rules_page.ts | 19 +- .../discover/search_source_alert.ts | 4 +- .../apps/observability/index.ts | 1 + .../pages/alerts/custom_threshold.ts | 254 ++++++++++++++++++ .../stack_alerting/index_threshold_rule.ts | 2 +- .../discover/search_source_alert.ts | 4 +- 12 files changed, 368 insertions(+), 19 deletions(-) create mode 100644 x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/custom_equation/metric_row_with_agg.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/custom_equation/metric_row_with_agg.tsx index 755911503d288..8cdb0c0b43c67 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/custom_equation/metric_row_with_agg.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/custom_equation/metric_row_with_agg.tsx @@ -142,7 +142,7 @@ export function MetricRowWithAgg({ } > )} diff --git a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx index d98b0a69d984f..3bb3641967753 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/custom_threshold/components/expression_row.tsx @@ -166,7 +166,7 @@ export const ExpressionRow: React.FC = (props) => { void; + dataTestSubj?: string; } -export const ClosablePopoverTitle = ({ children, onClose }: ClosablePopoverTitleProps) => { +export const ClosablePopoverTitle = ({ + children, + onClose, + dataTestSubj, +}: ClosablePopoverTitleProps) => { return ( - {children} + {children} { wrapper.find('[data-test-subj="thresholdPopover"]').last().simulate('click'); expect(wrapper.find('[data-test-subj="comparatorOptionsComboBox"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="alertThresholdInput"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="alertThresholdInput0"]').exists()).toBeTruthy(); wrapper - .find('[data-test-subj="alertThresholdInput"]') + .find('[data-test-subj="alertThresholdInput0"]') .last() .simulate('change', { target: { value: 1000 } }); expect(onChangeSelectedThreshold).toHaveBeenCalled(); @@ -145,21 +145,22 @@ describe('threshold expression', () => { wrapper.find('[data-test-subj="thresholdPopover"]').last().simulate('click'); expect(wrapper.find('[data-test-subj="comparatorOptionsComboBox"]').exists()).toBeTruthy(); - expect(wrapper.find('input[data-test-subj="alertThresholdInput"]').length).toEqual(1); + expect(wrapper.find('input[data-test-subj="alertThresholdInput0"]').length).toEqual(1); wrapper .find('[data-test-subj="comparatorOptionsComboBox"]') .last() .simulate('change', { target: { value: 'between' } }); wrapper.update(); - expect(wrapper.find('input[data-test-subj="alertThresholdInput"]').length).toEqual(2); + expect(wrapper.find('input[data-test-subj="alertThresholdInput0"]').length).toEqual(1); + expect(wrapper.find('input[data-test-subj="alertThresholdInput1"]').length).toEqual(1); wrapper .find('[data-test-subj="comparatorOptionsComboBox"]') .last() .simulate('change', { target: { value: '<' } }); wrapper.update(); - expect(wrapper.find('input[data-test-subj="alertThresholdInput"]').length).toEqual(1); + expect(wrapper.find('input[data-test-subj="alertThresholdInput0"]').length).toEqual(1); }); it('is valid when the threshold value is 0', () => { @@ -174,9 +175,9 @@ describe('threshold expression', () => { onChangeSelectedThresholdComparator={onChangeSelectedThresholdComparator} /> ); - expect(wrapper.find('[data-test-subj="alertThresholdInput"]')).toMatchInlineSnapshot(` + expect(wrapper.find('[data-test-subj="alertThresholdInput0"]')).toMatchInlineSnapshot(`
- setAlertThresholdPopoverOpen(false)}> + setAlertThresholdPopoverOpen(false)} + dataTestSubj="thresholdPopoverTitle" + > <>{comparators[comparator].text} @@ -154,7 +157,7 @@ export const ThresholdExpression = ({ error={errors[`threshold${i}`] as string[]} > 0 || isNil(threshold[i])} diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index dcac33b952e3e..7f327664f1b71 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -6,9 +6,11 @@ */ import expect from '@kbn/expect'; +import { ToolingLog } from '@kbn/tooling-log'; import { chunk } from 'lodash'; import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, AlertStatus } from '@kbn/rule-data-utils'; import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; +import { Agent as SuperTestAgent } from 'supertest'; import { FtrProviderContext } from '../../../ftr_provider_context'; // Based on the x-pack/test/functional/es_archives/observability/alerts archive. @@ -314,6 +316,69 @@ export function ObservabilityAlertsCommonProvider({ return value; }); + // Data view + const createDataView = async ({ + supertest, + id, + name, + title, + logger, + }: { + supertest: SuperTestAgent; + id: string; + name: string; + title: string; + logger: ToolingLog; + }) => { + const { body } = await supertest + .post(`/api/content_management/rpc/create`) + .set('kbn-xsrf', 'foo') + .send({ + contentTypeId: 'index-pattern', + data: { + fieldAttrs: '{}', + title, + timeFieldName: '@timestamp', + sourceFilters: '[]', + fields: '[]', + fieldFormatMap: '{}', + typeMeta: '{}', + runtimeFieldMap: '{}', + name, + }, + options: { id }, + version: 1, + }) + .expect(200); + + logger.debug(`Created data view: ${JSON.stringify(body)}`); + return body; + }; + + const deleteDataView = async ({ + supertest, + id, + logger, + }: { + supertest: SuperTestAgent; + id: string; + logger: ToolingLog; + }) => { + const { body } = await supertest + .post(`/api/content_management/rpc/delete`) + .set('kbn-xsrf', 'foo') + .send({ + contentTypeId: 'index-pattern', + id, + options: { force: true }, + version: 1, + }) + .expect(200); + + logger.debug(`Deleted data view id: ${id}`); + return body; + }; + return { getQueryBar, clearQueryBar, @@ -357,5 +422,7 @@ export function ObservabilityAlertsCommonProvider({ navigateToRulesLogsPage, navigateToRuleDetailsByRuleId, navigateToAlertDetails, + createDataView, + deleteDataView, }; } diff --git a/x-pack/test/functional/services/observability/alerts/rules_page.ts b/x-pack/test/functional/services/observability/alerts/rules_page.ts index 76f700f99b999..f5b16dc3914ab 100644 --- a/x-pack/test/functional/services/observability/alerts/rules_page.ts +++ b/x-pack/test/functional/services/observability/alerts/rules_page.ts @@ -7,6 +7,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; const METRIC_THRESHOLD_RULE_TYPE_SELECTOR = 'metrics.alert.threshold-SelectOption'; +const CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR = 'observability.rules.custom_threshold-SelectOption'; export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); @@ -18,8 +19,9 @@ export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderCont }; const clickCreateRuleButton = async () => { + await testSubjects.existOrFail('createRuleButton'); const createRuleButton = await testSubjects.find('createRuleButton'); - return createRuleButton.click(); + return await createRuleButton.click(); }; const clickRuleStatusDropDownMenu = async () => testSubjects.click('statusDropdown'); @@ -33,6 +35,7 @@ export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderCont }; const clickOnInfrastructureCategory = async () => { + await testSubjects.existOrFail('ruleTypeModal'); const categories = await testSubjects.find('ruleTypeModal'); const category = await categories.findByCssSelector(`.euiFacetButton[title="Infrastructure"]`); await category.click(); @@ -43,6 +46,18 @@ export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderCont await testSubjects.click(METRIC_THRESHOLD_RULE_TYPE_SELECTOR); }; + const clickOnObservabilityCategory = async () => { + await testSubjects.existOrFail('ruleTypeModal'); + const categories = await testSubjects.find('ruleTypeModal'); + const category = await categories.findByCssSelector(`.euiFacetButton[title="Observability"]`); + await category.click(); + }; + + const clickOnCustomThresholdRule = async () => { + await testSubjects.existOrFail(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR); + await testSubjects.click(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR); + }; + return { getManageRulesPageHref, clickCreateRuleButton, @@ -52,5 +67,7 @@ export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderCont clickOnRuleInEventLogs, clickOnInfrastructureCategory, clickOnMetricThresholdRule, + clickOnObservabilityCategory, + clickOnCustomThresholdRule, }; } 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 f16689bb3d22f..8c176c61530b7 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 @@ -163,7 +163,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return ruleName === alertName; }); await testSubjects.click('thresholdPopover'); - await testSubjects.setValue('alertThresholdInput', '1'); + await testSubjects.setValue('alertThresholdInput0', '1'); await testSubjects.click('forLastExpression'); await testSubjects.setValue('timeWindowSizeNumber', '30'); @@ -469,7 +469,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await filterBar.addFilter({ field: 'message.keyword', operation: 'is', value: 'msg-1' }); await testSubjects.click('thresholdPopover'); - await testSubjects.setValue('alertThresholdInput', '1'); + await testSubjects.setValue('alertThresholdInput0', '1'); await testSubjects.click('saveEditedRuleButton'); await PageObjects.header.waitUntilLoadingHasFinished(); diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index 64636e79123d7..96256248e5d88 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -17,6 +17,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./pages/alerts/rule_stats')); loadTestFile(require.resolve('./pages/alerts/state_synchronization')); loadTestFile(require.resolve('./pages/alerts/table_storage')); + loadTestFile(require.resolve('./pages/alerts/custom_threshold')); loadTestFile(require.resolve('./pages/cases/case_details')); loadTestFile(require.resolve('./pages/overview/alert_table')); loadTestFile(require.resolve('./exploratory_view')); diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts b/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts new file mode 100644 index 0000000000000..38d308a17e7b0 --- /dev/null +++ b/x-pack/test/observability_functional/apps/observability/pages/alerts/custom_threshold.ts @@ -0,0 +1,254 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Key } from 'selenium-webdriver'; +import expect from 'expect'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); + const kibanaServer = getService('kibanaServer'); + const supertest = getService('supertest'); + const find = getService('find'); + const logger = getService('log'); + const retry = getService('retry'); + + describe('Custom threshold rule', function () { + this.tags('includeFirefox'); + + const observability = getService('observability'); + const DATA_VIEW_1 = 'filebeat-*'; + const DATA_VIEW_1_ID = 'data-view-id_1'; + const DATA_VIEW_1_NAME = 'test-data-view-name_1'; + const DATA_VIEW_2 = 'metricbeat-*'; + const DATA_VIEW_2_ID = 'data-view-id_2'; + const DATA_VIEW_2_NAME = 'test-data-view-name_2'; + + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + // create two data views + await observability.alerts.common.createDataView({ + supertest, + name: DATA_VIEW_1_NAME, + id: DATA_VIEW_1_ID, + title: DATA_VIEW_1, + logger, + }); + await observability.alerts.common.createDataView({ + supertest, + name: DATA_VIEW_2_NAME, + id: DATA_VIEW_2_ID, + title: DATA_VIEW_2, + logger, + }); + await observability.alerts.common.navigateToRulesPage(); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + // This also deletes the created data views + await kibanaServer.savedObjects.cleanStandardList(); + }); + + it('shows the custom threshold rule in the observability section', async () => { + await observability.alerts.rulesPage.clickCreateRuleButton(); + await observability.alerts.rulesPage.clickOnObservabilityCategory(); + await observability.alerts.rulesPage.clickOnCustomThresholdRule(); + }); + + it('can add name and tags', async () => { + await testSubjects.setValue('ruleNameInput', 'test custom threshold rule'); + await testSubjects.setValue('comboBoxSearchInput', 'tag1'); + }); + + it('can add data view', async () => { + // select data view + await testSubjects.click('selectDataViewExpression'); + await testSubjects.setValue('indexPattern-switcher--input', 'test-data-view-name_2'); + const dataViewExpression = await find.byCssSelector( + '[data-test-subj="indexPattern-switcher--input"]' + ); + await dataViewExpression.pressKeys(Key.ENTER); + await retry.waitFor('data view selection to happen', async () => { + const dataViewSelector = await testSubjects.find('selectDataViewExpression'); + return (await dataViewSelector.getVisibleText()) === 'DATA VIEW\ntest-data-view-name_2'; + }); + }); + + it('can select aggregation', async () => { + // select aggregation + await testSubjects.click('aggregationNameA'); + await testSubjects.click('aggregationTypeSelect'); + // assert all options are available + await find.byCssSelector('option[value="avg"]'); + await find.byCssSelector('option[value="min"]'); + await find.byCssSelector('option[value="max"]'); + await find.byCssSelector('option[value="sum"]'); + await find.byCssSelector('option[value="count"]'); + await find.byCssSelector('option[value="cardinality"]'); + await find.byCssSelector('option[value="p99"]'); + await find.byCssSelector('option[value="p95"]'); + await find.byCssSelector('option[value="rate"]'); + + // set first aggregation + await find.clickByCssSelector(`option[value="avg"]`); + const input1 = await find.byCssSelector('[data-test-subj="aggregationField"] input'); + await input1.type('metricset.rtt'); + await testSubjects.click('o11yClosablePopoverTitleButton'); + await retry.waitFor('first aggregation to happen', async () => { + const aggregationNameA = await testSubjects.find('aggregationNameA'); + return (await aggregationNameA.getVisibleText()) === 'AVERAGE\nmetricset.rtt'; + }); + await new Promise((r) => setTimeout(r, 1000)); + + // set second aggregation + await testSubjects.click('thresholdRuleCustomEquationEditorAddAggregationFieldButton'); + await testSubjects.click('aggregationNameB'); + await testSubjects.setValue('o11ySearchField', 'service.name : "opbeans-node"'); + await testSubjects.click('o11yClosablePopoverTitleButton'); + await retry.waitFor('first aggregation to happen', async () => { + const aggregationNameB = await testSubjects.find('aggregationNameB'); + return (await aggregationNameB.getVisibleText()) === 'COUNT\nservice.name : "opbeans-node"'; + }); + await new Promise((r) => setTimeout(r, 1000)); + }); + + it('can set custom equation', async () => { + // set custom equation + await testSubjects.click('customEquation'); + const customEquationField = await find.byCssSelector( + '[data-test-subj="thresholdRuleCustomEquationEditorFieldText"]' + ); + await customEquationField.click(); + await customEquationField.type('A - B'); + await testSubjects.click('o11yClosablePopoverTitleButton'); + await retry.waitFor('custom equation update to happen', async () => { + const customEquation = await testSubjects.find('customEquation'); + return (await customEquation.getVisibleText()) === 'EQUATION\nA - B'; + }); + await new Promise((r) => setTimeout(r, 1000)); + }); + + it('can set threshold', async () => { + // set threshold + await testSubjects.click('thresholdPopover'); + await testSubjects.click('comparatorOptionsComboBox'); + // assert all options are available + await find.byCssSelector('option[value=">="]'); + await find.byCssSelector('option[value="<="]'); + await find.byCssSelector('option[value=">"]'); + await find.byCssSelector('option[value="<"]'); + await find.byCssSelector('option[value="between"]'); + await find.byCssSelector('option[value="notBetween"]'); + // select an option + await find.clickByCssSelector(`option[value="notBetween"]`); + const thresholdField1 = await find.byCssSelector('[data-test-subj="alertThresholdInput0"]'); + await thresholdField1.click(); + await new Promise((r) => setTimeout(r, 1000)); + await thresholdField1.pressKeys(Key.BACK_SPACE); + await new Promise((r) => setTimeout(r, 1000)); + await thresholdField1.pressKeys(Key.BACK_SPACE); + await new Promise((r) => setTimeout(r, 1000)); + await thresholdField1.pressKeys(Key.BACK_SPACE); + await thresholdField1.type('200'); + const thresholdField2 = await find.byCssSelector('[data-test-subj="alertThresholdInput1"]'); + await thresholdField2.type('250'); + await find.clickByCssSelector('[aria-label="Close"]'); + await retry.waitFor('comparator selection to happen', async () => { + const customEquation = await testSubjects.find('thresholdPopover'); + return (await customEquation.getVisibleText()) === 'IS NOT BETWEEN\n200 AND 250'; + }); + }); + + it('can set equation label', async () => { + // set equation label + await testSubjects.setValue( + 'thresholdRuleCustomEquationEditorFieldTextLabel', + 'test equation' + ); + }); + + it('can set time range', async () => { + // set time range + await testSubjects.click('forLastExpression'); + await new Promise((r) => setTimeout(r, 1000)); + const timeRangeField = await find.byCssSelector('[data-test-subj="timeWindowSizeNumber"]'); + await timeRangeField.click(); + await new Promise((r) => setTimeout(r, 1000)); + await timeRangeField.pressKeys(Key.BACK_SPACE); + await timeRangeField.type('2'); + // assert all options are available + await testSubjects.click('timeWindowUnitSelect'); + await find.byCssSelector('option[value="s"]'); + await find.byCssSelector('option[value="m"]'); + await find.byCssSelector('option[value="h"]'); + await find.byCssSelector('option[value="d"]'); + // select an option + await new Promise((r) => setTimeout(r, 3000)); + await find.clickByCssSelector('[data-test-subj="timeWindowUnitSelect"] option[value="d"]'); + await find.clickByCssSelector('[aria-label="Close"]'); + }); + + it('can set groupby', async () => { + // set group by + const groupByField = await find.byCssSelector( + '[data-test-subj="thresholdRuleMetricsExplorer-groupBy"] [data-test-subj="comboBoxSearchInput"]' + ); + await groupByField.type('docker.container.name'); + }); + + it('can save the rule', async () => { + await testSubjects.click('saveRuleButton'); + await testSubjects.click('confirmModalConfirmButton'); + await find.byCssSelector('button[title="test custom threshold rule"]'); + }); + + it('saved the rule correctly', async () => { + const { body: rules } = await supertest.get('/internal/alerting/rules/_find'); + + expect(rules.data.length).toEqual(1); + expect(rules.data[0]).toEqual( + expect.objectContaining({ + name: 'test custom threshold rule', + tags: ['tag1'], + params: expect.objectContaining({ + alertOnGroupDisappear: false, + alertOnNoData: false, + criteria: [ + { + comparator: 'notBetween', + label: 'test equation', + equation: 'A - B', + metrics: [ + { + aggType: 'avg', + field: 'metricset.rtt', + name: 'A', + }, + { + aggType: 'count', + filter: 'service.name : "opbeans-node"', + name: 'B', + }, + ], + threshold: [200, 250], + timeSize: 2, + timeUnit: 'd', + }, + ], + groupBy: ['docker.container.name'], + searchConfiguration: { + index: 'data-view-id_2', + query: { query: '', language: 'kuery' }, + }, + }), + }) + ); + }); + }); +}; diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts index 1155cf79a8e27..7d0b283a1f028 100644 --- a/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts @@ -81,7 +81,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await nameInput1.click(); await testSubjects.click('thresholdPopover'); - await testSubjects.setValue('alertThresholdInput', '420000'); + await testSubjects.setValue('alertThresholdInput0', '420000'); await testSubjects.click('forLastExpression'); await testSubjects.setValue('timeWindowSizeNumber', '24'); await testSubjects.setValue('timeWindowUnitSelect', 'hours'); diff --git a/x-pack/test_serverless/functional/test_suites/common/discover_ml_uptime/discover/search_source_alert.ts b/x-pack/test_serverless/functional/test_suites/common/discover_ml_uptime/discover/search_source_alert.ts index 897c67c717c05..d7f9e6f7450e6 100644 --- a/x-pack/test_serverless/functional/test_suites/common/discover_ml_uptime/discover/search_source_alert.ts +++ b/x-pack/test_serverless/functional/test_suites/common/discover_ml_uptime/discover/search_source_alert.ts @@ -195,7 +195,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return ruleName === alertName; }); await testSubjects.click('thresholdPopover'); - await testSubjects.setValue('alertThresholdInput', '1'); + await testSubjects.setValue('alertThresholdInput0', '1'); await testSubjects.click('forLastExpression'); await testSubjects.setValue('timeWindowSizeNumber', '30'); @@ -499,7 +499,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await filterBar.addFilter({ field: 'message.keyword', operation: 'is', value: 'msg-1' }); await testSubjects.click('thresholdPopover'); - await testSubjects.setValue('alertThresholdInput', '1'); + await testSubjects.setValue('alertThresholdInput0', '1'); await testSubjects.click('saveEditedRuleButton'); await PageObjects.header.waitUntilLoadingHasFinished();