[8.5] [ML] Adds anomaly alerts screenshot test suite (#146552) (#146860)

# Backport

This will backport the following commits from `main` to `8.5`:
- [[ML] Adds anomaly alerts screenshot test suite
(#146552)](https://github.com/elastic/kibana/pull/146552)

<!--- Backport version: 8.9.7 -->

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

<!--BACKPORT [{"author":{"name":"István Zoltán
Szabó","email":"szabosteve@gmail.com"},"sourceCommit":{"committedDate":"2022-12-02T10:01:51Z","message":"[ML]
Adds anomaly alerts screenshot test suite (#146552)\n\n##
Summary\r\n\r\nThis PR adds a new test suite to the screenshot creation
script that\r\ncovers the screenshots on [Generating alerts for anomaly
detection\r\njobs](https://www.elastic.co/guide/en/machine-learning/master/ml-configuring-alerts.html).","sha":"475e47ed993fba0ecd69caa211150f298e1eefe4","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":[":ml","release_note:skip","v8.6.0","v8.7.0","v8.5.3"],"number":146552,"url":"https://github.com/elastic/kibana/pull/146552","mergeCommit":{"message":"[ML]
Adds anomaly alerts screenshot test suite (#146552)\n\n##
Summary\r\n\r\nThis PR adds a new test suite to the screenshot creation
script that\r\ncovers the screenshots on [Generating alerts for anomaly
detection\r\njobs](https://www.elastic.co/guide/en/machine-learning/master/ml-configuring-alerts.html).","sha":"475e47ed993fba0ecd69caa211150f298e1eefe4"}},"sourceBranch":"main","suggestedTargetBranches":["8.6","8.5"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/146552","number":146552,"mergeCommit":{"message":"[ML]
Adds anomaly alerts screenshot test suite (#146552)\n\n##
Summary\r\n\r\nThis PR adds a new test suite to the screenshot creation
script that\r\ncovers the screenshots on [Generating alerts for anomaly
detection\r\njobs](https://www.elastic.co/guide/en/machine-learning/master/ml-configuring-alerts.html).","sha":"475e47ed993fba0ecd69caa211150f298e1eefe4"}},{"branch":"8.5","label":"v8.5.3","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: István Zoltán Szabó <szabosteve@gmail.com>
This commit is contained in:
Kibana Machine 2022-12-02 05:56:00 -05:00 committed by GitHub
parent 644c49d944
commit 36b9290cb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 238 additions and 5 deletions

View file

@ -171,6 +171,9 @@ export default async function ({ readConfigFile }) {
connectors: {
pathname: '/app/management/insightsAndAlerting/triggersActions/connectors',
},
triggersActions: {
pathname: '/app/management/insightsAndAlerting/triggersActions',
},
},
// choose where screenshots should be saved

View file

@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export function ActionsAPIServiceProvider({ getService }: FtrProviderContext) {
const kbnSupertest = getService('supertest');
const log = getService('log');
return {
async createConnector({
@ -37,10 +38,24 @@ export function ActionsAPIServiceProvider({ getService }: FtrProviderContext) {
},
async deleteConnector(id: string) {
return kbnSupertest
log.debug(`Deleting connector with id '${id}'...`);
const rsp = kbnSupertest
.delete(`/api/actions/connector/${id}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
log.debug('> Connector deleted.');
return rsp;
},
async deleteAllConnectors() {
const { body } = await kbnSupertest
.get(`/api/actions/connectors`)
.set('kbn-xsrf', 'foo')
.expect(200);
for (const connector of body) {
await this.deleteConnector(connector.id);
}
},
};
}

View file

@ -26,9 +26,9 @@ export function MachineLearningAlertingProvider(
return {
async selectAnomalyDetectionAlertType() {
await testSubjects.click('xpack.ml.anomaly_detection_alert-SelectOption');
await retry.tryForTime(5000, async () => {
await testSubjects.existOrFail(`mlAnomalyAlertForm`);
await testSubjects.click('xpack.ml.anomaly_detection_alert-SelectOption');
await testSubjects.existOrFail(`mlAnomalyAlertForm`, { timeout: 1000 });
});
},
@ -50,8 +50,14 @@ export function MachineLearningAlertingProvider(
},
async selectResultType(resultType: string) {
await testSubjects.click(`mlAnomalyAlertResult_${resultType}`);
await this.assertResultTypeSelection(resultType);
if (
(await testSubjects.exists(`mlAnomalyAlertResult_${resultType}_selected`, {
timeout: 1000,
})) === false
) {
await testSubjects.click(`mlAnomalyAlertResult_${resultType}`);
await this.assertResultTypeSelection(resultType);
}
},
async assertResultTypeSelection(resultType: string) {
@ -168,5 +174,56 @@ export function MachineLearningAlertingProvider(
mlApi.assertResponseStatusCode(204, status, body);
}
},
async openNotifySelection() {
await retry.tryForTime(5000, async () => {
await testSubjects.click('notifyWhenSelect');
await testSubjects.existOrFail('onActionGroupChange', { timeout: 1000 });
});
},
async setRuleName(rulename: string) {
await testSubjects.setValue('ruleNameInput', rulename);
},
async scrollRuleNameIntoView() {
await testSubjects.scrollIntoView('ruleNameInput');
},
async selectSlackConnectorType() {
await retry.tryForTime(5000, async () => {
await testSubjects.click('.slack-alerting-ActionTypeSelectOption');
await testSubjects.existOrFail('createActionConnectorButton-0', { timeout: 1000 });
});
},
async clickCreateConnectorButton() {
await retry.tryForTime(5000, async () => {
await testSubjects.click('createActionConnectorButton-0');
await testSubjects.existOrFail('connectorAddModal', { timeout: 1000 });
});
},
async setConnectorName(connectorname: string) {
await testSubjects.setValue('nameInput', connectorname);
},
async setWebhookUrl(webhookurl: string) {
await testSubjects.setValue('slackWebhookUrlInput', webhookurl);
},
async clickSaveActionButton() {
await retry.tryForTime(5000, async () => {
await testSubjects.click('saveActionButtonModal');
await testSubjects.existOrFail('addNewActionConnectorActionGroup-0', { timeout: 1000 });
});
},
async openAddRuleVariable() {
await retry.tryForTime(5000, async () => {
await testSubjects.click('messageAddVariableButton');
await testSubjects.existOrFail('variableMenuButton-alert.actionGroup', { timeout: 1000 });
});
},
};
}

View file

@ -0,0 +1,155 @@
/*
* 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 type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { DATAFEED_STATE } from '@kbn/ml-plugin/common/constants/states';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ECOMMERCE_INDEX_PATTERN } from '..';
function createTestJobAndDatafeed() {
const timestamp = Date.now();
const jobId = `high_sum_total_sales_${timestamp}`;
return {
job: {
job_id: jobId,
description: 'test_job',
groups: ['ecommerce'],
analysis_config: {
bucket_span: '1h',
detectors: [
{
detector_description: 'High total sales',
function: 'high_sum',
field_name: 'taxful_total_price',
over_field_name: 'customer_full_name.keyword',
detector_index: 0,
},
],
influencers: ['customer_full_name.keyword', 'category.keyword'],
},
data_description: {
time_field: 'order_date',
time_format: 'epoch_ms',
},
analysis_limits: {
model_memory_limit: '13mb',
categorization_examples_limit: 4,
},
},
datafeed: {
datafeed_id: `datafeed-${jobId}`,
job_id: jobId,
query: {
bool: {
must: [
{
match_all: {},
},
],
filter: [],
must_not: [],
},
},
query_delay: '120s',
indices: [ECOMMERCE_INDEX_PATTERN],
} as unknown as estypes.MlDatafeed,
};
}
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const esArchiver = getService('esArchiver');
const ml = getService('ml');
const pageObjects = getPageObjects(['triggersActionsUI']);
const commonScreenshots = getService('commonScreenshots');
const browser = getService('browser');
const actions = getService('actions');
const screenshotDirectories = ['ml_docs', 'anomaly_detection'];
let testJobId = '';
describe('anomaly detection alert', function () {
before(async () => {
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce');
await ml.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date');
const { job, datafeed } = createTestJobAndDatafeed();
testJobId = job.job_id;
// Set up jobs
// @ts-expect-error not full interface
await ml.api.createAnomalyDetectionJob(job);
await ml.api.openAnomalyDetectionJob(job.job_id);
await ml.api.createDatafeed(datafeed);
await ml.api.startDatafeed(datafeed.datafeed_id);
await ml.api.waitForDatafeedState(datafeed.datafeed_id, DATAFEED_STATE.STARTED);
await ml.api.assertJobResultsExist(job.job_id);
});
after(async () => {
await ml.api.deleteAnomalyDetectionJobES(testJobId);
await ml.api.cleanMlIndices();
await ml.alerting.cleanAnomalyDetectionRules();
await actions.api.deleteAllConnectors();
});
describe('overview page alert flyout controls', () => {
it('alert flyout screenshot', async () => {
await ml.navigation.navigateToAlertsAndAction();
await pageObjects.triggersActionsUI.clickCreateAlertButton();
await ml.alerting.setRuleName('test-ecommerce');
await ml.alerting.openNotifySelection();
await commonScreenshots.takeScreenshot('ml-rule', screenshotDirectories, 1920, 1400);
// close popover
await browser.pressKeys(browser.keys.ESCAPE);
await ml.alerting.selectAnomalyDetectionAlertType();
await ml.testExecution.logTestStep('should have correct default values');
await ml.alerting.assertSeverity(75);
await ml.alerting.assertPreviewButtonState(false);
await ml.testExecution.logTestStep('should complete the alert params');
await ml.alerting.selectJobs([testJobId]);
await ml.alerting.selectResultType('bucket');
await ml.alerting.setSeverity(75);
await ml.testExecution.logTestStep('should populate advanced settings with default values');
await ml.alerting.assertTopNBuckets(1);
await ml.alerting.assertLookbackInterval('123m');
await ml.testExecution.logTestStep('should preview the alert condition');
await ml.alerting.assertPreviewButtonState(false);
await ml.alerting.setTestInterval('1y');
await ml.alerting.assertPreviewButtonState(true);
await ml.alerting.scrollRuleNameIntoView();
await ml.testExecution.logTestStep('take screenshot');
await commonScreenshots.takeScreenshot(
'ml-anomaly-alert-severity',
screenshotDirectories,
1920,
1400
);
await ml.alerting.selectSlackConnectorType();
await ml.testExecution.logTestStep('should open connectors');
await ml.alerting.clickCreateConnectorButton();
await ml.alerting.setConnectorName('test-connector');
await ml.alerting.setWebhookUrl('https://www.elastic.co');
await ml.alerting.clickSaveActionButton();
await ml.alerting.openAddRuleVariable();
await ml.testExecution.logTestStep('take screenshot');
await commonScreenshots.takeScreenshot(
'ml-anomaly-alert-messages',
screenshotDirectories,
1920,
1400
);
});
});
});
};

View file

@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('anomaly detection', function () {
loadTestFile(require.resolve('./geographic_data'));
loadTestFile(require.resolve('./generate_anomaly_alerts'));
loadTestFile(require.resolve('./population_analysis'));
loadTestFile(require.resolve('./custom_urls'));
loadTestFile(require.resolve('./mapping_anomalies'));

View file

@ -8,6 +8,7 @@
import Fs from 'fs';
import { CA_CERT_PATH } from '@kbn/dev-utils';
import { FtrConfigProviderContext } from '@kbn/test';
import { pageObjects } from './page_objects';
import { services } from './services';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
@ -28,6 +29,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
// default to the xpack functional config
...xpackFunctionalConfig.getAll(),
servers,
pageObjects,
services,
testFiles: [require.resolve('./apps')],
junit: {