From a0125432bac658ec38c914b7429c0a448370d20a Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Sat, 17 Oct 2020 10:38:03 +0530 Subject: [PATCH 1/9] resolves https://github.com/elastic/kibana/issues/78148 --- .../components/builtin_alert_types/threshold/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index d7ce73ce0c7d9..886c75668ed77 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { lazy } from 'react'; - +import { i18n } from '@kbn/i18n'; import { AlertTypeModel } from '../../../../types'; import { validateExpression } from './validation'; import { IndexThresholdAlertParams } from './types'; @@ -17,6 +17,12 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts iconClass: 'alert', alertParamsExpression: lazy(() => import('./expression')), validate: validateExpression, + defaultActionMessage: i18n.translate( + 'xpack.triggers_actions_ui.builtin_alert_types.threshold.alertDefaultActionMessage', + { + defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{context.window\\}\\} on \\{\\{context.date\\}\\}`, + } + ), requiresAppContext: false, }; } From c5808a05c484992f0528adb66b075f986b914402 Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Wed, 21 Oct 2020 11:29:56 +0530 Subject: [PATCH 2/9] required changes done for https://github.com/elastic/kibana/issues/78148 --- .../index_threshold/action_context.ts | 12 +++++----- .../alert_types/index_threshold/alert_type.ts | 23 +++++++++++++++++++ .../builtin_alert_types/threshold/index.ts | 2 +- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts index 5135e31e9322c..b89bf6a1e27da 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts @@ -27,6 +27,10 @@ export interface BaseActionContext extends AlertInstanceContext { date: string; // the value that met the threshold value: number; + // the function that is used + function: string; + // the time window for aggregation + window: string; } export function addMessages( @@ -42,10 +46,6 @@ export function addMessages( }, }); - const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`; - const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`; - - const window = `${params.timeWindowSize}${params.timeWindowUnit}`; const message = i18n.translate( 'xpack.stackAlerts.indexThreshold.alertTypeContextMessageDescription', { @@ -55,8 +55,8 @@ export function addMessages( name: alertInfo.name, group: baseContext.group, value: baseContext.value, - function: humanFn, - window, + function: baseContext.function, + window: baseContext.window, date: baseContext.date, }, } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts index 2a1ed429b7fe1..3adfbeb0c0112 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts @@ -83,6 +83,20 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action } ); + const actionVariableContextFunctionLabel = i18n.translate( + 'xpack.stackAlerts.indexThreshold.actionVariableContextFunctionLabel', + { + defaultMessage: 'A string formatted values combining threshold comparator and threshold', + } + ); + + const actionVariableContextWindowLabel = i18n.translate( + 'xpack.stackAlerts.indexThreshold.actionVariableContextWindowLabel', + { + defaultMessage: 'A string formatted values combining time window size and time window unit', + } + ); + const alertParamsVariables = Object.keys(CoreQueryParamsSchemaProperties).map( (propKey: string) => { return { @@ -107,6 +121,8 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action { name: 'group', description: actionVariableContextGroupLabel }, { name: 'date', description: actionVariableContextDateLabel }, { name: 'value', description: actionVariableContextValueLabel }, + { name: 'function', description: actionVariableContextFunctionLabel }, + { name: 'window', description: actionVariableContextWindowLabel }, ], params: [ { name: 'threshold', description: actionVariableContextThresholdLabel }, @@ -160,10 +176,17 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action if (!met) continue; + const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`; + const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`; + + const window = `${params.timeWindowSize}${params.timeWindowUnit}`; + const baseContext: BaseActionContext = { date, group: instanceId, value, + function: humanFn, + window, }; const actionContext = addMessages(options, baseContext, params); const alertInstance = options.services.alertInstanceFactory(instanceId); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index 886c75668ed77..cf9c35ffd3bd3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -18,7 +18,7 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts alertParamsExpression: lazy(() => import('./expression')), validate: validateExpression, defaultActionMessage: i18n.translate( - 'xpack.triggers_actions_ui.builtin_alert_types.threshold.alertDefaultActionMessage', + 'xpack.triggersActionsUI.builtin_alert_types.threshold.alertDefaultActionMessage', { defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{context.window\\}\\} on \\{\\{context.date\\}\\}`, } From e00826b285448cc2207660639367df313e9e21eb Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Wed, 21 Oct 2020 21:34:32 +0530 Subject: [PATCH 3/9] requested changes done https://github.com/elastic/kibana/issues/78148 --- .../alert_types/index_threshold/action_context.ts | 5 ++--- .../alert_types/index_threshold/alert_type.ts | 13 +------------ .../builtin_alert_types/threshold/index.ts | 2 +- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts index b89bf6a1e27da..9bb0df9d07fd4 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.ts @@ -29,8 +29,6 @@ export interface BaseActionContext extends AlertInstanceContext { value: number; // the function that is used function: string; - // the time window for aggregation - window: string; } export function addMessages( @@ -46,6 +44,7 @@ export function addMessages( }, }); + const window = `${params.timeWindowSize}${params.timeWindowUnit}`; const message = i18n.translate( 'xpack.stackAlerts.indexThreshold.alertTypeContextMessageDescription', { @@ -56,7 +55,7 @@ export function addMessages( group: baseContext.group, value: baseContext.value, function: baseContext.function, - window: baseContext.window, + window, date: baseContext.date, }, } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts index 3adfbeb0c0112..e0a9cd981dac0 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.ts @@ -86,14 +86,7 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action const actionVariableContextFunctionLabel = i18n.translate( 'xpack.stackAlerts.indexThreshold.actionVariableContextFunctionLabel', { - defaultMessage: 'A string formatted values combining threshold comparator and threshold', - } - ); - - const actionVariableContextWindowLabel = i18n.translate( - 'xpack.stackAlerts.indexThreshold.actionVariableContextWindowLabel', - { - defaultMessage: 'A string formatted values combining time window size and time window unit', + defaultMessage: 'A string describing the threshold comparator and threshold', } ); @@ -122,7 +115,6 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action { name: 'date', description: actionVariableContextDateLabel }, { name: 'value', description: actionVariableContextValueLabel }, { name: 'function', description: actionVariableContextFunctionLabel }, - { name: 'window', description: actionVariableContextWindowLabel }, ], params: [ { name: 'threshold', description: actionVariableContextThresholdLabel }, @@ -179,14 +171,11 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`; const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`; - const window = `${params.timeWindowSize}${params.timeWindowUnit}`; - const baseContext: BaseActionContext = { date, group: instanceId, value, function: humanFn, - window, }; const actionContext = addMessages(options, baseContext, params); const alertInstance = options.services.alertInstanceFactory(instanceId); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index cf9c35ffd3bd3..4f0ac9b2c6406 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -20,7 +20,7 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts defaultActionMessage: i18n.translate( 'xpack.triggersActionsUI.builtin_alert_types.threshold.alertDefaultActionMessage', { - defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{context.window\\}\\} on \\{\\{context.date\\}\\}`, + defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{params.timeWindowSize\\}\\}\\{\\{params.timeWindowUnit\\}\\} on \\{\\{context.date\\}\\}`, } ), requiresAppContext: false, From 86c0e5b095a9096cee8b4eff80b3495f6afbe93c Mon Sep 17 00:00:00 2001 From: Patrick Mueller <pmuellr@gmail.com> Date: Wed, 21 Oct 2020 22:58:51 -0400 Subject: [PATCH 4/9] functional tests for index threshold default action message --- .../index_threshold/alert.ts | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts index 92db0458c0639..33025b1986be4 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts @@ -15,6 +15,9 @@ import { ObjectRemover, } from '../../../../../common/lib'; import { createEsDocuments } from './create_test_data'; +// import { getAlertType } from '../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/alert'; +import { getAlertType } from '../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/'; +// ../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/alert.ts const ALERT_TYPE_ID = '.index-threshold'; const ACTION_TYPE_ID = '.index'; @@ -26,6 +29,8 @@ const ALERT_INTERVALS_TO_WRITE = 5; const ALERT_INTERVAL_SECONDS = 3; const ALERT_INTERVAL_MILLIS = ALERT_INTERVAL_SECONDS * 1000; +const DefaultActionMessage = getAlertType().defaultActionMessage; + // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); @@ -62,6 +67,10 @@ export default function alertTests({ getService }: FtrProviderContext) { await esTestIndexToolOutput.destroy(); }); + it('has a default action message', () => { + expect(DefaultActionMessage).to.be.ok(); + }); + // The tests below create two alerts, one that will fire, one that will // never fire; the tests ensure the ones that should fire, do fire, and // those that shouldn't fire, do not fire. @@ -85,7 +94,7 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(2); for (const doc of docs) { const { group } = doc._source; - const { name, value, title, message } = doc._source.params; + const { name, title, message } = doc._source.params; expect(name).to.be('always fire'); expect(group).to.be('all documents'); @@ -93,9 +102,8 @@ export default function alertTests({ getService }: FtrProviderContext) { // we'll check title and message in this test, but not subsequent ones expect(title).to.be('alert always fire group all documents exceeded threshold'); - const expectedPrefix = `alert always fire group all documents value ${value} exceeded threshold count > -1 over`; - const messagePrefix = message.substr(0, expectedPrefix.length); - expect(messagePrefix).to.be(expectedPrefix); + const messagePattern = /alert always fire group all documents value \d+ exceeded threshold count > -1 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -128,10 +136,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-0') inGroup0++; + + const messagePattern = /alert always fire group group-\d value \d+ exceeded threshold count .+ over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-0, rando split between others @@ -163,9 +174,12 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(2); for (const doc of docs) { - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); + + const messagePattern = /alert always fire group all documents value \d+ exceeded threshold sum\(testedValue\) between 0,1000000 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -195,9 +209,12 @@ export default function alertTests({ getService }: FtrProviderContext) { const docs = await waitForDocs(4); for (const doc of docs) { - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); + + const messagePattern = /alert always fire group all documents value .+ exceeded threshold avg\(testedValue\) .+ 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } }); @@ -232,10 +249,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-2') inGroup2++; + + const messagePattern = /alert always fire group group-. value \d+ exceeded threshold max\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-2, rando split between others @@ -274,10 +294,13 @@ export default function alertTests({ getService }: FtrProviderContext) { for (const doc of docs) { const { group } = doc._source; - const { name } = doc._source.params; + const { name, message } = doc._source.params; expect(name).to.be('always fire'); if (group === 'group-0') inGroup0++; + + const messagePattern = /alert always fire group group-. value \d+ exceeded threshold min\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; + expect(message).to.match(messagePattern); } // there should be 2 docs in group-0, rando split between others @@ -329,7 +352,7 @@ export default function alertTests({ getService }: FtrProviderContext) { name: '{{{alertName}}}', value: '{{{context.value}}}', title: '{{{context.title}}}', - message: '{{{context.message}}}', + message: DefaultActionMessage, }, date: '{{{context.date}}}', // TODO: I wanted to write the alert value here, but how? From 4cc33bca7ea0506dc0141b14f0e3493dd6586681 Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Thu, 22 Oct 2020 20:56:09 +0530 Subject: [PATCH 5/9] resolved type-check and jest errors --- .../server/alert_types/index_threshold/action_context.test.ts | 3 +++ .../server/alert_types/index_threshold/alert_type.test.ts | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.test.ts index 3f5addb77cb33..48847686828a9 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/action_context.test.ts @@ -25,6 +25,7 @@ describe('ActionContext', () => { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 42, + function: 'count > 4', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( @@ -53,6 +54,7 @@ describe('ActionContext', () => { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 42, + function: 'avg([aggField]) > 4.2', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( @@ -80,6 +82,7 @@ describe('ActionContext', () => { date: '2020-01-01T00:00:00.000Z', group: '[group]', value: 4, + function: 'count between 4,5', }; const context = addMessages({ name: '[alert-name]' }, base, params); expect(context.title).toMatchInlineSnapshot( diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts index e33a3e775ca96..0d17175178890 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts @@ -46,6 +46,10 @@ describe('alertType', () => { "description": "The value that exceeded the threshold.", "name": "value", }, + Object { + "description": "A string describing the threshold comparator and threshold", + "name": "function", + }, ], "params": Array [ Object { From 5830f138ccc6f3203bba5ec8d5e3b5994a73fa3d Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Fri, 30 Oct 2020 01:23:54 +0530 Subject: [PATCH 6/9] added functional UI test for defaultActionMessage --- .../apps/triggers_actions_ui/alerts.ts | 452 ++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts new file mode 100644 index 0000000000000..f41e1f58bb233 --- /dev/null +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts @@ -0,0 +1,452 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import uuid from 'uuid'; +import { times } from 'lodash'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +function generateUniqueKey() { + return uuid.v4().replace(/-/g, ''); +} + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); + const supertest = getService('supertest'); + const find = getService('find'); + const retry = getService('retry'); + + async function createAlert(overwrites: Record<string, any> = {}) { + const { body: createdAlert } = await supertest + .post(`/api/alerts/alert`) + .set('kbn-xsrf', 'foo') + .send({ + enabled: true, + name: generateUniqueKey(), + tags: ['foo', 'bar'], + alertTypeId: 'test.noop', + consumer: 'alerts', + schedule: { interval: '1m' }, + throttle: '1m', + actions: [], + params: {}, + ...overwrites, + }) + .expect(200); + return createdAlert; + } + + async function getAlertsByName(name: string) { + const { + body: { data: alerts }, + } = await supertest.get(`/api/alerts/_find?search=${name}&search_fields=name`).expect(200); + + return alerts; + } + + async function deleteAlerts(alertIds: string[]) { + alertIds.forEach(async (alertId: string) => { + await supertest.delete(`/api/alerts/alert/${alertId}`).set('kbn-xsrf', 'foo').expect(204, ''); + }); + } + + async function defineAlert(alertName: string) { + await pageObjects.triggersActionsUI.clickCreateAlertButton(); + await testSubjects.setValue('alertNameInput', alertName); + await testSubjects.click('.index-threshold-SelectOption'); + await testSubjects.click('selectIndexExpression'); + const comboBox = await find.byCssSelector('#indexSelectSearchBox'); + await comboBox.click(); + await comboBox.type('k'); + const filterSelectItem = await find.byCssSelector(`.euiFilterSelectItem`); + await filterSelectItem.click(); + await testSubjects.click('thresholdAlertTimeFieldSelect'); + await retry.try(async () => { + const fieldOptions = await find.allByCssSelector('#thresholdTimeField option'); + expect(fieldOptions[1]).not.to.be(undefined); + await fieldOptions[1].click(); + }); + await testSubjects.click('closePopover'); + // need this two out of popup clicks to close them + const nameInput = await testSubjects.find('alertNameInput'); + await nameInput.click(); + } + + describe('alerts', function () { + before(async () => { + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('alertsTab'); + }); + + it('should create an alert', async () => { + const alertName = generateUniqueKey(); + await defineAlert(alertName); + + await testSubjects.click('.slack-ActionTypeSelectOption'); + await testSubjects.click('addNewActionConnectorButton-.slack'); + const slackConnectorName = generateUniqueKey(); + await testSubjects.setValue('nameInput', slackConnectorName); + await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); + await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); + const createdConnectorToastTitle = await pageObjects.common.closeToast(); + expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); + expect(await messageTextArea.getAttribute('value')).to.eql('alert {{alertName}} group {{context.group}} value {{context.value}} exceeded threshold {{context.function}} over {{params.timeWindowSize}}{{params.timeWindowUnit}} on {{context.date}}'); + await testSubjects.setValue('messageTextArea', 'test message '); + await testSubjects.click('messageAddVariableButton'); + await testSubjects.click('variableMenuButton-0'); + expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}'); + await messageTextArea.type(' some additional text '); + + await testSubjects.click('messageAddVariableButton'); + await testSubjects.click('variableMenuButton-1'); + + expect(await messageTextArea.getAttribute('value')).to.eql( + 'test message {{alertId}} some additional text {{alertInstanceId}}' + ); + + await testSubjects.click('saveAlertButton'); + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql(`Created alert "${alertName}"`); + await pageObjects.triggersActionsUI.searchAlerts(alertName); + const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResultsAfterSave).to.eql([ + { + name: alertName, + tagsText: '', + alertType: 'Index threshold', + interval: '1m', + }, + ]); + + // clean up created alert + const alertsToDelete = await getAlertsByName(alertName); + await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); + }); + + it('should show save confirmation before creating alert with no actions', async () => { + const alertName = generateUniqueKey(); + await defineAlert(alertName); + + await testSubjects.click('saveAlertButton'); + await testSubjects.existOrFail('confirmAlertSaveModal'); + await testSubjects.click('confirmAlertSaveModal > confirmModalCancelButton'); + await testSubjects.missingOrFail('confirmAlertSaveModal'); + await find.existsByCssSelector('[data-test-subj="saveAlertButton"]:not(disabled)'); + + await testSubjects.click('saveAlertButton'); + await testSubjects.existOrFail('confirmAlertSaveModal'); + await testSubjects.click('confirmAlertSaveModal > confirmModalConfirmButton'); + await testSubjects.missingOrFail('confirmAlertSaveModal'); + + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql(`Created alert "${alertName}"`); + await pageObjects.triggersActionsUI.searchAlerts(alertName); + const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResultsAfterSave).to.eql([ + { + name: alertName, + tagsText: '', + alertType: 'Index threshold', + interval: '1m', + }, + ]); + + // clean up created alert + const alertsToDelete = await getAlertsByName(alertName); + await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); + }); + + it('should display alerts in alphabetical order', async () => { + const uniqueKey = generateUniqueKey(); + const a = await createAlert({ name: 'b', tags: [uniqueKey] }); + const b = await createAlert({ name: 'c', tags: [uniqueKey] }); + const c = await createAlert({ name: 'a', tags: [uniqueKey] }); + + await pageObjects.triggersActionsUI.searchAlerts(uniqueKey); + + const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResults).to.have.length(3); + expect(searchResults[0].name).to.eql('a'); + expect(searchResults[1].name).to.eql('b'); + expect(searchResults[2].name).to.eql('c'); + + await deleteAlerts([a.id, b.id, c.id]); + }); + + it('should search for alert', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResults).to.eql([ + { + name: createdAlert.name, + tagsText: 'foo, bar', + alertType: 'Test: Noop', + interval: '1m', + }, + ]); + await deleteAlerts([createdAlert.id]); + }); + + it('should search for tags', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(`${createdAlert.name} foo`); + + const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResults).to.eql([ + { + name: createdAlert.name, + tagsText: 'foo, bar', + alertType: 'Test: Noop', + interval: '1m', + }, + ]); + await deleteAlerts([createdAlert.id]); + }); + + it('should display an empty list when search did not return any alerts', async () => { + await pageObjects.triggersActionsUI.searchAlerts(`An Alert That For Sure Doesn't Exist!`); + + expect(await pageObjects.triggersActionsUI.isAlertsListDisplayed()).to.eql(true); + }); + + it('should disable single alert', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const disableSwitchAfterDisable = await testSubjects.find('disableSwitch'); + const isChecked = await disableSwitchAfterDisable.getAttribute('aria-checked'); + expect(isChecked).to.eql('true'); + await deleteAlerts([createdAlert.id]); + }); + + it('should re-enable single alert', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const disableSwitchAfterReEnable = await testSubjects.find('disableSwitch'); + const isChecked = await disableSwitchAfterReEnable.getAttribute('aria-checked'); + expect(isChecked).to.eql('false'); + await deleteAlerts([createdAlert.id]); + }); + + it('should mute single alert', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const muteSwitchAfterMute = await testSubjects.find('muteSwitch'); + const isChecked = await muteSwitchAfterMute.getAttribute('aria-checked'); + expect(isChecked).to.eql('true'); + await deleteAlerts([createdAlert.id]); + }); + + it('should unmute single alert', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const muteSwitchAfterUnmute = await testSubjects.find('muteSwitch'); + const isChecked = await muteSwitchAfterUnmute.getAttribute('aria-checked'); + expect(isChecked).to.eql('false'); + await deleteAlerts([createdAlert.id]); + }); + + it('should delete single alert', async () => { + const firstAlert = await createAlert(); + const secondAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(secondAlert.name); + + await testSubjects.click('collapsedItemActions'); + + await testSubjects.click('deleteAlert'); + await testSubjects.existOrFail('deleteIdsConfirmation'); + await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); + await testSubjects.missingOrFail('deleteIdsConfirmation'); + + await retry.try(async () => { + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql('Deleted 1 alert'); + }); + + await pageObjects.triggersActionsUI.searchAlerts(secondAlert.name); + const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResultsAfterDelete.length).to.eql(0); + await deleteAlerts([firstAlert.id]); + }); + + it('should mute all selection', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); + + await testSubjects.click('bulkAction'); + + await testSubjects.click('muteAll'); + + // Unmute all button shows after clicking mute all + await testSubjects.existOrFail('unmuteAll'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const muteSwitch = await testSubjects.find('muteSwitch'); + const isChecked = await muteSwitch.getAttribute('aria-checked'); + expect(isChecked).to.eql('true'); + await deleteAlerts([createdAlert.id]); + }); + + it('should unmute all selection', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); + + await testSubjects.click('bulkAction'); + + await testSubjects.click('muteAll'); + + await testSubjects.click('unmuteAll'); + + // Mute all button shows after clicking unmute all + await testSubjects.existOrFail('muteAll'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const muteSwitch = await testSubjects.find('muteSwitch'); + const isChecked = await muteSwitch.getAttribute('aria-checked'); + expect(isChecked).to.eql('false'); + await deleteAlerts([createdAlert.id]); + }); + + it('should disable all selection', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); + + await testSubjects.click('bulkAction'); + + await testSubjects.click('disableAll'); + + // Enable all button shows after clicking disable all + await testSubjects.existOrFail('enableAll'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const disableSwitch = await testSubjects.find('disableSwitch'); + const isChecked = await disableSwitch.getAttribute('aria-checked'); + expect(isChecked).to.eql('true'); + await deleteAlerts([createdAlert.id]); + }); + + it('should enable all selection', async () => { + const createdAlert = await createAlert(); + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); + + await testSubjects.click('bulkAction'); + + await testSubjects.click('disableAll'); + + await testSubjects.click('enableAll'); + + // Disable all button shows after clicking enable all + await testSubjects.existOrFail('disableAll'); + + await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); + + await testSubjects.click('collapsedItemActions'); + + const disableSwitch = await testSubjects.find('disableSwitch'); + const isChecked = await disableSwitch.getAttribute('aria-checked'); + expect(isChecked).to.eql('false'); + await deleteAlerts([createdAlert.id]); + }); + + it('should delete all selection', async () => { + const namePrefix = generateUniqueKey(); + let count = 0; + const createdAlertsFirstPage = await Promise.all( + times(2, () => createAlert({ name: `${namePrefix}-0${count++}` })) + ); + + await pageObjects.triggersActionsUI.searchAlerts(namePrefix); + + for (const createdAlert of createdAlertsFirstPage) { + await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); + } + + await testSubjects.click('bulkAction'); + + await testSubjects.click('deleteAll'); + await testSubjects.existOrFail('deleteIdsConfirmation'); + await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); + await testSubjects.missingOrFail('deleteIdsConfirmation'); + + await retry.tryForTime(30000, async () => { + const toastTitle = await pageObjects.common.closeToast(); + expect(toastTitle).to.eql('Deleted 2 alerts'); + }); + + await pageObjects.triggersActionsUI.searchAlerts(namePrefix); + const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getAlertsList(); + expect(searchResultsAfterDelete).to.have.length(0); + }); + }); +}; From ebb3fee0c0487842d71fb62bd40a6b182867232c Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Tue, 3 Nov 2020 01:43:38 +0530 Subject: [PATCH 7/9] added functional UI test to an existing test --- .../alert_create_flyout.ts | 5 +- .../apps/triggers_actions_ui/alerts.ts | 452 ------------------ 2 files changed, 4 insertions(+), 453 deletions(-) delete mode 100644 x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts 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 7d99d3635106d..78af11b416782 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 @@ -73,10 +73,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); const createdConnectorToastTitle = await pageObjects.common.closeToast(); expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); + expect(await messageTextArea.getAttribute('value')).to.eql( + 'alert {{alertName}} group {{context.group}} value {{context.value}} exceeded threshold {{context.function}} over {{params.timeWindowSize}}{{params.timeWindowUnit}} on {{context.date}}' + ); await testSubjects.setValue('messageTextArea', 'test message '); await testSubjects.click('messageAddVariableButton'); await testSubjects.click('variableMenuButton-0'); - const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}'); await messageTextArea.type(' some additional text '); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts deleted file mode 100644 index f41e1f58bb233..0000000000000 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import uuid from 'uuid'; -import { times } from 'lodash'; -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -function generateUniqueKey() { - return uuid.v4().replace(/-/g, ''); -} - -export default ({ getPageObjects, getService }: FtrProviderContext) => { - const testSubjects = getService('testSubjects'); - const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); - const supertest = getService('supertest'); - const find = getService('find'); - const retry = getService('retry'); - - async function createAlert(overwrites: Record<string, any> = {}) { - const { body: createdAlert } = await supertest - .post(`/api/alerts/alert`) - .set('kbn-xsrf', 'foo') - .send({ - enabled: true, - name: generateUniqueKey(), - tags: ['foo', 'bar'], - alertTypeId: 'test.noop', - consumer: 'alerts', - schedule: { interval: '1m' }, - throttle: '1m', - actions: [], - params: {}, - ...overwrites, - }) - .expect(200); - return createdAlert; - } - - async function getAlertsByName(name: string) { - const { - body: { data: alerts }, - } = await supertest.get(`/api/alerts/_find?search=${name}&search_fields=name`).expect(200); - - return alerts; - } - - async function deleteAlerts(alertIds: string[]) { - alertIds.forEach(async (alertId: string) => { - await supertest.delete(`/api/alerts/alert/${alertId}`).set('kbn-xsrf', 'foo').expect(204, ''); - }); - } - - async function defineAlert(alertName: string) { - await pageObjects.triggersActionsUI.clickCreateAlertButton(); - await testSubjects.setValue('alertNameInput', alertName); - await testSubjects.click('.index-threshold-SelectOption'); - await testSubjects.click('selectIndexExpression'); - const comboBox = await find.byCssSelector('#indexSelectSearchBox'); - await comboBox.click(); - await comboBox.type('k'); - const filterSelectItem = await find.byCssSelector(`.euiFilterSelectItem`); - await filterSelectItem.click(); - await testSubjects.click('thresholdAlertTimeFieldSelect'); - await retry.try(async () => { - const fieldOptions = await find.allByCssSelector('#thresholdTimeField option'); - expect(fieldOptions[1]).not.to.be(undefined); - await fieldOptions[1].click(); - }); - await testSubjects.click('closePopover'); - // need this two out of popup clicks to close them - const nameInput = await testSubjects.find('alertNameInput'); - await nameInput.click(); - } - - describe('alerts', function () { - before(async () => { - await pageObjects.common.navigateToApp('triggersActions'); - await testSubjects.click('alertsTab'); - }); - - it('should create an alert', async () => { - const alertName = generateUniqueKey(); - await defineAlert(alertName); - - await testSubjects.click('.slack-ActionTypeSelectOption'); - await testSubjects.click('addNewActionConnectorButton-.slack'); - const slackConnectorName = generateUniqueKey(); - await testSubjects.setValue('nameInput', slackConnectorName); - await testSubjects.setValue('slackWebhookUrlInput', 'https://test'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); - const createdConnectorToastTitle = await pageObjects.common.closeToast(); - expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`); - const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); - expect(await messageTextArea.getAttribute('value')).to.eql('alert {{alertName}} group {{context.group}} value {{context.value}} exceeded threshold {{context.function}} over {{params.timeWindowSize}}{{params.timeWindowUnit}} on {{context.date}}'); - await testSubjects.setValue('messageTextArea', 'test message '); - await testSubjects.click('messageAddVariableButton'); - await testSubjects.click('variableMenuButton-0'); - expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}'); - await messageTextArea.type(' some additional text '); - - await testSubjects.click('messageAddVariableButton'); - await testSubjects.click('variableMenuButton-1'); - - expect(await messageTextArea.getAttribute('value')).to.eql( - 'test message {{alertId}} some additional text {{alertInstanceId}}' - ); - - await testSubjects.click('saveAlertButton'); - const toastTitle = await pageObjects.common.closeToast(); - expect(toastTitle).to.eql(`Created alert "${alertName}"`); - await pageObjects.triggersActionsUI.searchAlerts(alertName); - const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResultsAfterSave).to.eql([ - { - name: alertName, - tagsText: '', - alertType: 'Index threshold', - interval: '1m', - }, - ]); - - // clean up created alert - const alertsToDelete = await getAlertsByName(alertName); - await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); - }); - - it('should show save confirmation before creating alert with no actions', async () => { - const alertName = generateUniqueKey(); - await defineAlert(alertName); - - await testSubjects.click('saveAlertButton'); - await testSubjects.existOrFail('confirmAlertSaveModal'); - await testSubjects.click('confirmAlertSaveModal > confirmModalCancelButton'); - await testSubjects.missingOrFail('confirmAlertSaveModal'); - await find.existsByCssSelector('[data-test-subj="saveAlertButton"]:not(disabled)'); - - await testSubjects.click('saveAlertButton'); - await testSubjects.existOrFail('confirmAlertSaveModal'); - await testSubjects.click('confirmAlertSaveModal > confirmModalConfirmButton'); - await testSubjects.missingOrFail('confirmAlertSaveModal'); - - const toastTitle = await pageObjects.common.closeToast(); - expect(toastTitle).to.eql(`Created alert "${alertName}"`); - await pageObjects.triggersActionsUI.searchAlerts(alertName); - const searchResultsAfterSave = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResultsAfterSave).to.eql([ - { - name: alertName, - tagsText: '', - alertType: 'Index threshold', - interval: '1m', - }, - ]); - - // clean up created alert - const alertsToDelete = await getAlertsByName(alertName); - await deleteAlerts(alertsToDelete.map((alertItem: { id: string }) => alertItem.id)); - }); - - it('should display alerts in alphabetical order', async () => { - const uniqueKey = generateUniqueKey(); - const a = await createAlert({ name: 'b', tags: [uniqueKey] }); - const b = await createAlert({ name: 'c', tags: [uniqueKey] }); - const c = await createAlert({ name: 'a', tags: [uniqueKey] }); - - await pageObjects.triggersActionsUI.searchAlerts(uniqueKey); - - const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResults).to.have.length(3); - expect(searchResults[0].name).to.eql('a'); - expect(searchResults[1].name).to.eql('b'); - expect(searchResults[2].name).to.eql('c'); - - await deleteAlerts([a.id, b.id, c.id]); - }); - - it('should search for alert', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResults).to.eql([ - { - name: createdAlert.name, - tagsText: 'foo, bar', - alertType: 'Test: Noop', - interval: '1m', - }, - ]); - await deleteAlerts([createdAlert.id]); - }); - - it('should search for tags', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(`${createdAlert.name} foo`); - - const searchResults = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResults).to.eql([ - { - name: createdAlert.name, - tagsText: 'foo, bar', - alertType: 'Test: Noop', - interval: '1m', - }, - ]); - await deleteAlerts([createdAlert.id]); - }); - - it('should display an empty list when search did not return any alerts', async () => { - await pageObjects.triggersActionsUI.searchAlerts(`An Alert That For Sure Doesn't Exist!`); - - expect(await pageObjects.triggersActionsUI.isAlertsListDisplayed()).to.eql(true); - }); - - it('should disable single alert', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const disableSwitchAfterDisable = await testSubjects.find('disableSwitch'); - const isChecked = await disableSwitchAfterDisable.getAttribute('aria-checked'); - expect(isChecked).to.eql('true'); - await deleteAlerts([createdAlert.id]); - }); - - it('should re-enable single alert', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('disableSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const disableSwitchAfterReEnable = await testSubjects.find('disableSwitch'); - const isChecked = await disableSwitchAfterReEnable.getAttribute('aria-checked'); - expect(isChecked).to.eql('false'); - await deleteAlerts([createdAlert.id]); - }); - - it('should mute single alert', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const muteSwitchAfterMute = await testSubjects.find('muteSwitch'); - const isChecked = await muteSwitchAfterMute.getAttribute('aria-checked'); - expect(isChecked).to.eql('true'); - await deleteAlerts([createdAlert.id]); - }); - - it('should unmute single alert', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await pageObjects.triggersActionsUI.toggleSwitch('muteSwitch'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const muteSwitchAfterUnmute = await testSubjects.find('muteSwitch'); - const isChecked = await muteSwitchAfterUnmute.getAttribute('aria-checked'); - expect(isChecked).to.eql('false'); - await deleteAlerts([createdAlert.id]); - }); - - it('should delete single alert', async () => { - const firstAlert = await createAlert(); - const secondAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(secondAlert.name); - - await testSubjects.click('collapsedItemActions'); - - await testSubjects.click('deleteAlert'); - await testSubjects.existOrFail('deleteIdsConfirmation'); - await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); - await testSubjects.missingOrFail('deleteIdsConfirmation'); - - await retry.try(async () => { - const toastTitle = await pageObjects.common.closeToast(); - expect(toastTitle).to.eql('Deleted 1 alert'); - }); - - await pageObjects.triggersActionsUI.searchAlerts(secondAlert.name); - const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResultsAfterDelete.length).to.eql(0); - await deleteAlerts([firstAlert.id]); - }); - - it('should mute all selection', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - - await testSubjects.click('bulkAction'); - - await testSubjects.click('muteAll'); - - // Unmute all button shows after clicking mute all - await testSubjects.existOrFail('unmuteAll'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const muteSwitch = await testSubjects.find('muteSwitch'); - const isChecked = await muteSwitch.getAttribute('aria-checked'); - expect(isChecked).to.eql('true'); - await deleteAlerts([createdAlert.id]); - }); - - it('should unmute all selection', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - - await testSubjects.click('bulkAction'); - - await testSubjects.click('muteAll'); - - await testSubjects.click('unmuteAll'); - - // Mute all button shows after clicking unmute all - await testSubjects.existOrFail('muteAll'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const muteSwitch = await testSubjects.find('muteSwitch'); - const isChecked = await muteSwitch.getAttribute('aria-checked'); - expect(isChecked).to.eql('false'); - await deleteAlerts([createdAlert.id]); - }); - - it('should disable all selection', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - - await testSubjects.click('bulkAction'); - - await testSubjects.click('disableAll'); - - // Enable all button shows after clicking disable all - await testSubjects.existOrFail('enableAll'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const disableSwitch = await testSubjects.find('disableSwitch'); - const isChecked = await disableSwitch.getAttribute('aria-checked'); - expect(isChecked).to.eql('true'); - await deleteAlerts([createdAlert.id]); - }); - - it('should enable all selection', async () => { - const createdAlert = await createAlert(); - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - - await testSubjects.click('bulkAction'); - - await testSubjects.click('disableAll'); - - await testSubjects.click('enableAll'); - - // Disable all button shows after clicking enable all - await testSubjects.existOrFail('disableAll'); - - await pageObjects.triggersActionsUI.searchAlerts(createdAlert.name); - - await testSubjects.click('collapsedItemActions'); - - const disableSwitch = await testSubjects.find('disableSwitch'); - const isChecked = await disableSwitch.getAttribute('aria-checked'); - expect(isChecked).to.eql('false'); - await deleteAlerts([createdAlert.id]); - }); - - it('should delete all selection', async () => { - const namePrefix = generateUniqueKey(); - let count = 0; - const createdAlertsFirstPage = await Promise.all( - times(2, () => createAlert({ name: `${namePrefix}-0${count++}` })) - ); - - await pageObjects.triggersActionsUI.searchAlerts(namePrefix); - - for (const createdAlert of createdAlertsFirstPage) { - await testSubjects.click(`checkboxSelectRow-${createdAlert.id}`); - } - - await testSubjects.click('bulkAction'); - - await testSubjects.click('deleteAll'); - await testSubjects.existOrFail('deleteIdsConfirmation'); - await testSubjects.click('deleteIdsConfirmation > confirmModalConfirmButton'); - await testSubjects.missingOrFail('deleteIdsConfirmation'); - - await retry.tryForTime(30000, async () => { - const toastTitle = await pageObjects.common.closeToast(); - expect(toastTitle).to.eql('Deleted 2 alerts'); - }); - - await pageObjects.triggersActionsUI.searchAlerts(namePrefix); - const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getAlertsList(); - expect(searchResultsAfterDelete).to.have.length(0); - }); - }); -}; From a519a6db7ccc501149cfb62aa03c5f34c9853a40 Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Tue, 3 Nov 2020 19:57:58 +0530 Subject: [PATCH 8/9] remove comments in x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts --- .../tests/alerting/builtin_alert_types/index_threshold/alert.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts index 33025b1986be4..c05fa6cf051ff 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts @@ -15,9 +15,7 @@ import { ObjectRemover, } from '../../../../../common/lib'; import { createEsDocuments } from './create_test_data'; -// import { getAlertType } from '../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/alert'; import { getAlertType } from '../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/'; -// ../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/alert.ts const ALERT_TYPE_ID = '.index-threshold'; const ACTION_TYPE_ID = '.index'; From a137daf6982d4eff44e41fa0978227ad3d393f25 Mon Sep 17 00:00:00 2001 From: dB2510 <dhruvbodani2510@gmail.com> Date: Sat, 7 Nov 2020 01:33:01 +0530 Subject: [PATCH 9/9] fix: i18n labels corrected to camelcase --- .../components/builtin_alert_types/threshold/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts index dcfbb503e3001..a5b2fbb37e838 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/index.ts @@ -26,7 +26,7 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts alertParamsExpression: lazy(() => import('./expression')), validate: validateExpression, defaultActionMessage: i18n.translate( - 'xpack.triggersActionsUI.builtin_alert_types.threshold.alertDefaultActionMessage', + 'xpack.triggersActionsUI.components.builtinAlertTypes.threshold.alertDefaultActionMessage', { defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{params.timeWindowSize\\}\\}\\{\\{params.timeWindowUnit\\}\\} on \\{\\{context.date\\}\\}`, }