Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Observability] add custom threshold functional test #184602

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0870aa5
observability - add custom threshold functional test
dominiqueclarke May 31, 2024
3b3a32e
adjust tests
dominiqueclarke Jun 3, 2024
51d15ff
adjust tests
dominiqueclarke Jun 3, 2024
8668126
Merge branch 'chore/observability-custom-threshold-functional-test' o…
dominiqueclarke Jun 3, 2024
6d6cf00
adjust tests
dominiqueclarke Jun 4, 2024
5d82bc3
Merge branch 'main' of https://github.com/elastic/kibana into chore/o…
dominiqueclarke Jun 6, 2024
caf50c4
adjust test
dominiqueclarke Jun 7, 2024
e054ec5
Merge branch 'main' of https://github.com/elastic/kibana into chore/o…
dominiqueclarke Jul 17, 2024
bf49166
update selector and data
dominiqueclarke Jul 17, 2024
34d5482
Merge branch 'main' into chore/observability-custom-threshold-functio…
dominiqueclarke Jul 19, 2024
64f1f58
Merge branch 'main' into chore/observability-custom-threshold-functio…
dominiqueclarke Jul 19, 2024
80fd847
adjust expected value
dominiqueclarke Jul 22, 2024
154258d
Merge branch 'main' into chore/observability-custom-threshold-functio…
dominiqueclarke Jul 22, 2024
edb29db
Fix setting equation
maryam-saeidi Jul 22, 2024
dda84b9
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Jul 22, 2024
345caa2
Merge branch 'main' into chore/observability-custom-threshold-functio…
dominiqueclarke Jul 30, 2024
7e2ecf1
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Sep 12, 2024
d638063
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Sep 13, 2024
3be7c53
Create data view using createDataView helper
maryam-saeidi Sep 13, 2024
58eb831
Fix flakiness
maryam-saeidi Sep 16, 2024
9450b4a
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Sep 16, 2024
a77fea8
Fix type and flakiness
maryam-saeidi Sep 16, 2024
99f6d24
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Sep 16, 2024
1dd8fc8
Another attempt for fixing flakiness
maryam-saeidi Sep 17, 2024
0778b1a
Merge branch 'main' into chore/observability-custom-threshold-functio…
maryam-saeidi Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -228,6 +228,7 @@ export function MetricRowWithAgg({
options={fieldOptions}
selectedOptions={field ? [{ label: field }] : []}
onChange={handleFieldChange}
data-test-subj="aggregationField"
/>
</EuiFormRow>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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', () => {
Expand All @@ -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]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ export const ThresholdExpression = ({
repositionOnScroll
>
<div>
<ClosablePopoverTitle onClose={() => setAlertThresholdPopoverOpen(false)}>
<ClosablePopoverTitle
onClose={() => setAlertThresholdPopoverOpen(false)}
dataTestSubj="thresholdPopoverTitle"
>
<>{comparators[comparator].text}</>
</ClosablePopoverTitle>
<EuiFlexGroup>
Expand Down Expand Up @@ -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])}
Expand Down
67 changes: 67 additions & 0 deletions x-pack/test/functional/services/observability/alerts/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -357,5 +422,7 @@ export function ObservabilityAlertsCommonProvider({
navigateToRulesLogsPage,
navigateToRuleDetailsByRuleId,
navigateToAlertDetails,
createDataView,
deleteDataView,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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');
Expand All @@ -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();
Expand All @@ -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();
Comment on lines +52 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
const category = await categories.findByCssSelector(`.euiFacetButton[title="Observability"]`);
await category.click();
await category.clickByCssSelector(`.euiFacetButton[title="Observability"]`);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following error when using clickByCssSelector:

fail: ObservabilityApp Custom threshold rule shows the custom threshold rule in the observability section
       │      TypeError: categories.clickByCssSelector is not a function

};

const clickOnCustomThresholdRule = async () => {
await testSubjects.existOrFail(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR);
await testSubjects.click(CUSTOM_THRESHOLD_RULE_TYPE_SELECTOR);
};

return {
getManageRulesPageHref,
clickCreateRuleButton,
Expand All @@ -52,5 +67,7 @@ export function ObservabilityAlertsRulesProvider({ getService }: FtrProviderCont
clickOnRuleInEventLogs,
clickOnInfrastructureCategory,
clickOnMetricThresholdRule,
clickOnObservabilityCategory,
clickOnCustomThresholdRule,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand Down
Loading