[8.x] [Observability] add custom threshold functional test (#184602) (#193248)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Observability] add custom threshold functional test
(#184602)](https://github.com/elastic/kibana/pull/184602)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Dominique
Clarke","email":"dominique.clarke@elastic.co"},"sourceCommit":{"committedDate":"2024-09-18T07:56:58Z","message":"[Observability]
add custom threshold functional test (#184602)\n\nCloses
#175301\r\n\r\n##
Summary\r\n\r\nResolves\r\nhttps://github.com/orgs/elastic/projects/1375/views/1?pane=issue&itemId=50879015\r\n\r\nTo
run\r\n```\r\ncd x-pack && node ../scripts/functional_tests_server
--config=test/observability_functional/with_rac_write.config.ts\r\n\r\nor\r\n\r\nnode
scripts/functional_tests_server.js --config
x-pack/test/observability_functional/with_rac_write.config.ts\r\n```\r\nIn
a different terminal\r\n```\r\nnode ../scripts/functional_test_runner
--config=test/observability_functional/with_rac_write.config.ts --grep
\"Custom threshold rule\"\r\n\r\nor\r\n\r\nnode
scripts/functional_test_runner
--config=x-pack/test/observability_functional/with_rac_write.config.ts
--grep \"Custom threshold
rule\"\r\n```\r\n\r\n---------\r\n\r\nCo-authored-by: Maryam Saeidi
<maryam.saeidi@elastic.co>","sha":"0241cf690c631d4865b9c412240ab49357646a26","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["chore","release_note:skip","v9.0.0","ci:project-deploy-observability","Team:obs-ux-management","v8.16.0"],"title":"[Observability]
add custom threshold functional
test","number":184602,"url":"https://github.com/elastic/kibana/pull/184602","mergeCommit":{"message":"[Observability]
add custom threshold functional test (#184602)\n\nCloses
#175301\r\n\r\n##
Summary\r\n\r\nResolves\r\nhttps://github.com/orgs/elastic/projects/1375/views/1?pane=issue&itemId=50879015\r\n\r\nTo
run\r\n```\r\ncd x-pack && node ../scripts/functional_tests_server
--config=test/observability_functional/with_rac_write.config.ts\r\n\r\nor\r\n\r\nnode
scripts/functional_tests_server.js --config
x-pack/test/observability_functional/with_rac_write.config.ts\r\n```\r\nIn
a different terminal\r\n```\r\nnode ../scripts/functional_test_runner
--config=test/observability_functional/with_rac_write.config.ts --grep
\"Custom threshold rule\"\r\n\r\nor\r\n\r\nnode
scripts/functional_test_runner
--config=x-pack/test/observability_functional/with_rac_write.config.ts
--grep \"Custom threshold
rule\"\r\n```\r\n\r\n---------\r\n\r\nCo-authored-by: Maryam Saeidi
<maryam.saeidi@elastic.co>","sha":"0241cf690c631d4865b9c412240ab49357646a26"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/184602","number":184602,"mergeCommit":{"message":"[Observability]
add custom threshold functional test (#184602)\n\nCloses
#175301\r\n\r\n##
Summary\r\n\r\nResolves\r\nhttps://github.com/orgs/elastic/projects/1375/views/1?pane=issue&itemId=50879015\r\n\r\nTo
run\r\n```\r\ncd x-pack && node ../scripts/functional_tests_server
--config=test/observability_functional/with_rac_write.config.ts\r\n\r\nor\r\n\r\nnode
scripts/functional_tests_server.js --config
x-pack/test/observability_functional/with_rac_write.config.ts\r\n```\r\nIn
a different terminal\r\n```\r\nnode ../scripts/functional_test_runner
--config=test/observability_functional/with_rac_write.config.ts --grep
\"Custom threshold rule\"\r\n\r\nor\r\n\r\nnode
scripts/functional_test_runner
--config=x-pack/test/observability_functional/with_rac_write.config.ts
--grep \"Custom threshold
rule\"\r\n```\r\n\r\n---------\r\n\r\nCo-authored-by: Maryam Saeidi
<maryam.saeidi@elastic.co>","sha":"0241cf690c631d4865b9c412240ab49357646a26"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Dominique Clarke <dominique.clarke@elastic.co>
This commit is contained in:
Kibana Machine 2024-09-18 19:32:36 +10:00 committed by GitHub
parent 4b862c0794
commit a197fb196b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 368 additions and 19 deletions

View file

@ -142,7 +142,7 @@ export function MetricRowWithAgg({
}
>
<EuiExpression
data-test-subj="aggregationName"
data-test-subj={`aggregationName${name}`}
description={aggregationTypes[aggType].text}
value={aggType === Aggregators.COUNT ? filter || DEFAULT_COUNT_FILTER_TITLE : field}
isActive={aggTypePopoverOpen}
@ -228,6 +228,7 @@ export function MetricRowWithAgg({
options={fieldOptions}
selectedOptions={field ? [{ label: field }] : []}
onChange={handleFieldChange}
data-test-subj="aggregationField"
/>
</EuiFormRow>
)}

View file

@ -166,7 +166,7 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = (props) => {
<EuiFlexItem>
<EuiFormRow label={LABEL_LABEL} fullWidth helpText={LABEL_HELP_MESSAGE}>
<EuiFieldText
data-test-subj="thresholdRuleCustomEquationEditorFieldText"
data-test-subj="thresholdRuleCustomEquationEditorFieldTextLabel"
compressed
fullWidth
value={label}

View file

@ -12,13 +12,18 @@ import { EuiPopoverTitle, EuiFlexGroup, EuiFlexItem, EuiButtonIcon } from '@elas
interface ClosablePopoverTitleProps {
children: JSX.Element;
onClose: () => void;
dataTestSubj?: string;
}
export const ClosablePopoverTitle = ({ children, onClose }: ClosablePopoverTitleProps) => {
export const ClosablePopoverTitle = ({
children,
onClose,
dataTestSubj,
}: ClosablePopoverTitleProps) => {
return (
<EuiPopoverTitle>
<EuiFlexGroup alignItems="center" gutterSize="s">
<EuiFlexItem>{children}</EuiFlexItem>
<EuiFlexItem data-test-subj={dataTestSubj}>{children}</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType="cross"

View file

@ -89,10 +89,10 @@ describe('threshold expression', () => {
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(`
<EuiFieldNumber
data-test-subj="alertThresholdInput"
data-test-subj="alertThresholdInput0"
isInvalid={false}
min={0}
onChange={[Function]}

View file

@ -120,7 +120,10 @@ export const ThresholdExpression = ({
repositionOnScroll
>
<div>
<ClosablePopoverTitle onClose={() => setAlertThresholdPopoverOpen(false)}>
<ClosablePopoverTitle
onClose={() => setAlertThresholdPopoverOpen(false)}
dataTestSubj="thresholdPopoverTitle"
>
<>{comparators[comparator].text}</>
</ClosablePopoverTitle>
<EuiFlexGroup>
@ -154,7 +157,7 @@ export const ThresholdExpression = ({
error={errors[`threshold${i}`] as string[]}
>
<EuiFieldNumber
data-test-subj="alertThresholdInput"
data-test-subj={`alertThresholdInput${i}`}
min={0}
value={!threshold || threshold[i] === undefined ? '' : threshold[i]}
isInvalid={Number(errors[`threshold${i}`]?.length) > 0 || isNil(threshold[i])}

View file

@ -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,
};
}

View file

@ -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,
};
}

View file

@ -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();

View file

@ -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'));

View file

@ -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' },
},
}),
})
);
});
});
};

View file

@ -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');

View file

@ -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();