diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx index d6f8b23229f6c..eebd3d8aeb14d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx @@ -89,10 +89,7 @@ export const MonitorPageTitle: React.FC = () => { - + diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/__snapshots__/enable_alert.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/__snapshots__/enable_alert.test.tsx.snap deleted file mode 100644 index 486414ab8a052..0000000000000 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/__snapshots__/enable_alert.test.tsx.snap +++ /dev/null @@ -1,89 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EnableAlertComponent renders without errors for valid props 1`] = ` -
-
-
- -
-
-
-`; - -exports[`EnableAlertComponent shallow renders without errors for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.test.tsx index a325edc243129..8aa63504df813 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.test.tsx @@ -7,112 +7,86 @@ import React from 'react'; import { EnableMonitorAlert } from './enable_alert'; -import * as redux from 'react-redux'; -import { - mountWithRouterRedux, - renderWithRouterRedux, - shallowWithRouterRedux, -} from '../../../../lib'; -import { EuiPopover, EuiText } from '@elastic/eui'; +import { fireEvent } from '@testing-library/dom'; + import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../../common/constants'; -import { ReactRouterEuiLink } from '../../../common/react_router_helpers'; +import { makePing } from '../../../../../common/runtime_types/ping'; +import { render } from '../../../../lib/helper/rtl_helpers'; +import { DISABLE_STATUS_ALERT, ENABLE_STATUS_ALERT } from './translations'; +import { mockState } from '../../../../lib/__mocks__/uptime_store.mock'; +import { AlertsResult } from '../../../../state/actions/types'; describe('EnableAlertComponent', () => { - let defaultConnectors: string[] = []; - let alerts: any = []; - - beforeEach(() => { - jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn()); - - jest.spyOn(redux, 'useSelector').mockImplementation((fn, d) => { - if (fn.name === 'selectDynamicSettings') { - return { - settings: Object.assign(DYNAMIC_SETTINGS_DEFAULTS, { - defaultConnectors, - }), - }; - } - if (fn.name === 'alertsSelector') { - return { - data: { - data: alerts, - }, - loading: false, - }; - } - return {}; - }); - }); - - it('shallow renders without errors for valid props', () => { - const wrapper = shallowWithRouterRedux( - + it('it displays define connectors when there is none', () => { + const { getByTestId, getByLabelText, getByText } = render( + ); - expect(wrapper).toMatchSnapshot(); - }); + expect(getByTestId('uptimeDisplayDefineConnector')); + expect(getByLabelText(ENABLE_STATUS_ALERT)); - it('renders without errors for valid props', () => { - const wrapper = renderWithRouterRedux( - - ); - expect(wrapper).toMatchSnapshot(); - }); + fireEvent.click(getByTestId('uptimeDisplayDefineConnector')); - it('displays define connectors when there is none', () => { - defaultConnectors = []; - const wrapper = mountWithRouterRedux( - + expect(getByTestId('uptimeSettingsLink')).toHaveAttribute( + 'href', + '/settings?focusConnectorField=true' ); - expect(wrapper.find(EuiPopover)).toHaveLength(1); - wrapper.find('button').simulate('click'); - expect(wrapper.find(EuiText).text()).toBe( - 'To start enabling alerts, please define a default alert action connector in Settings' + expect( + getByText('To start enabling alerts, please define a default alert action connector in') ); - expect(wrapper.find(ReactRouterEuiLink)).toMatchInlineSnapshot(` - - - - - Settings - - - - - `); }); it('does not displays define connectors when there is connector', () => { - defaultConnectors = ['infra-slack-connector-id']; - const wrapper = mountWithRouterRedux( - + const defaultConnectors = ['infra-slack-connector-id']; + + const { getByTestId, getByLabelText } = render( + , + { + state: { + dynamicSettings: { + settings: { ...DYNAMIC_SETTINGS_DEFAULTS, defaultConnectors }, + loading: false, + }, + }, + } ); - expect(wrapper.find(EuiPopover)).toHaveLength(0); + expect(getByTestId('uptimeEnableSimpleDownAlerttestMonitor')); + expect(getByLabelText(ENABLE_STATUS_ALERT)); }); it('displays disable when alert is there', () => { - alerts = [{ id: 'test-alert', params: { search: 'testMonitor' } }]; - defaultConnectors = ['infra-slack-connector-id']; + const alerts = [{ id: 'test-alert', params: { search: 'testMonitor' } }]; + const defaultConnectors = ['infra-slack-connector-id']; - const wrapper = mountWithRouterRedux( - + const { getByTestId, getByLabelText } = render( + , + { + state: { + dynamicSettings: { + settings: { ...DYNAMIC_SETTINGS_DEFAULTS, defaultConnectors }, + loading: false, + }, + alerts: { + ...mockState.alerts, + alerts: { + data: ({ data: alerts } as unknown) as AlertsResult, + loading: false, + }, + }, + }, + } ); - expect(wrapper.find('button').prop('aria-label')).toBe('Disable status alert'); + expect(getByTestId('uptimeDisableSimpleDownAlerttestMonitor')); + expect(getByLabelText(DISABLE_STATUS_ALERT)); }); }); diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.tsx index 444198bfa9412..f0f7c4d91c4f5 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/enable_alert.tsx @@ -21,13 +21,14 @@ import { import { MONITOR_ROUTE } from '../../../../../common/constants'; import { DefineAlertConnectors } from './define_connectors'; import { DISABLE_STATUS_ALERT, ENABLE_STATUS_ALERT } from './translations'; +import { Ping } from '../../../../../common/runtime_types/ping'; interface Props { monitorId: string; - monitorName?: string; + selectedMonitor: Ping; } -export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => { +export const EnableMonitorAlert = ({ monitorId, selectedMonitor }: Props) => { const [isLoading, setIsLoading] = useState(false); const { settings } = useSelector(selectDynamicSettings); @@ -66,7 +67,7 @@ export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => { createAlertAction.get({ defaultActions, monitorId, - monitorName, + selectedMonitor, }) ); setIsLoading(true); @@ -102,28 +103,26 @@ export const EnableMonitorAlert = ({ monitorId, monitorName }: Props) => { return hasDefaultConnectors || hasAlert ? (
- { - - <> - {' '} - {showSpinner && } - - - } + + <> + {' '} + {showSpinner && } + +
) : ( diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx index ebac6b0f77c24..9a0054f77252e 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx @@ -142,7 +142,7 @@ export const MonitorListComponent: ({ render: (item: MonitorSummary) => ( ), }, diff --git a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx index b5933fa51b398..5f6f9d7a7207e 100644 --- a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx @@ -55,6 +55,7 @@ describe('SyntheticsCallout', () => { grow={false} > { grow={false} > { { if (shouldShow) { hideSyntheticsCallout(); diff --git a/x-pack/plugins/uptime/public/state/api/alert_actions.test.ts b/x-pack/plugins/uptime/public/state/api/alert_actions.test.ts new file mode 100644 index 0000000000000..15fb95f5d4a4d --- /dev/null +++ b/x-pack/plugins/uptime/public/state/api/alert_actions.test.ts @@ -0,0 +1,130 @@ +/* + * 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 { populateAlertActions } from './alert_actions'; +import { ActionConnector } from '../alerts/alerts'; + +const selectedMonitor = { + docId: 'X5dkPncBy0xTcvZ347hy', + timestamp: '2021-01-26T11:12:14.519Z', + '@timestamp': '2021-01-26T11:12:14.519Z', + url: { scheme: 'tcp', domain: 'localhost', port: 18278, full: 'tcp://localhost:18278' }, + error: { type: 'io', message: 'dial tcp 127.0.0.1:18278: connect: connection refused' }, + ecs: { version: '1.7.0' }, + resolve: { ip: '127.0.0.1', rtt: { us: 410 } }, + summary: { down: 1, up: 0 }, + monitor: { + ip: '127.0.0.1', + name: 'Always Down Local Port', + type: 'tcp', + timespan: { gte: '2021-01-26T11:12:14.519Z', lt: '2021-01-26T11:17:14.519Z' }, + id: 'always-down', + status: 'down', + duration: { us: 695 }, + check_group: 'a53b0003-5fc6-11eb-9241-42010a84000f', + }, + event: { dataset: 'uptime' }, + agent: { + ephemeral_id: '7d86e765-9f29-46e6-b1ec-047b09b4074e', + id: '7c9d2825-614f-4906-a13e-c9db1c6e5585', + name: 'gke-edge-oblt-edge-oblt-pool-c9faf257-m1ci', + type: 'heartbeat', + version: '8.0.0', + }, +}; + +describe('Alert Actions factory', () => { + it('generate expected action for pager duty', async () => { + const resp = populateAlertActions({ + selectedMonitor, + defaultActions: ([ + { + actionTypeId: '.pagerduty', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: + 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown) as ActionConnector[], + }); + expect(resp).toEqual([ + { + actionTypeId: '.pagerduty', + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'resolve', + summary: + 'Monitor Always Down Local Port with url tcp://localhost:18278 has recovered with status Up', + }, + }, + { + actionTypeId: '.pagerduty', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: + 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', + }, + }, + ]); + }); + + it('generate expected action for slack action connector', async () => { + const resp = populateAlertActions({ + selectedMonitor, + defaultActions: ([ + { + actionTypeId: '.pagerduty', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: + 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown) as ActionConnector[], + }); + expect(resp).toEqual([ + { + actionTypeId: '.pagerduty', + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'resolve', + summary: + 'Monitor Always Down Local Port with url tcp://localhost:18278 has recovered with status Up', + }, + }, + { + actionTypeId: '.pagerduty', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: + 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', + }, + }, + ]); + }); +}); diff --git a/x-pack/plugins/uptime/public/state/api/alert_actions.ts b/x-pack/plugins/uptime/public/state/api/alert_actions.ts index 592fd56984707..fff5fa9a67804 100644 --- a/x-pack/plugins/uptime/public/state/api/alert_actions.ts +++ b/x-pack/plugins/uptime/public/state/api/alert_actions.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { NewAlertParams } from './alerts'; import { AlertAction } from '../../../../triggers_actions_ui/public'; import { ACTION_GROUP_DEFINITIONS } from '../../../common/constants/alerts'; @@ -19,6 +20,7 @@ import { // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../actions/server'; import { ActionTypeId } from '../../components/settings/types'; +import { Ping } from '../../../common/runtime_types/ping'; export const SLACK_ACTION_ID: ActionTypeId = '.slack'; export const PAGER_DUTY_ACTION_ID: ActionTypeId = '.pagerduty'; @@ -31,7 +33,17 @@ export const WEBHOOK_ACTION_ID: ActionTypeId = '.webhook'; const { MONITOR_STATUS } = ACTION_GROUP_DEFINITIONS; -export function populateAlertActions({ defaultActions, monitorId, monitorName }: NewAlertParams) { +const getRecoveryMessage = (selectedMonitor: Ping) => { + return i18n.translate('xpack.uptime.alerts.monitorStatus.recoveryMessage', { + defaultMessage: 'Monitor {monitor} with url {url} has recovered with status Up', + values: { + monitor: selectedMonitor?.monitor?.name || selectedMonitor?.monitor?.id, + url: selectedMonitor?.url?.full, + }, + }); +}; + +export function populateAlertActions({ defaultActions, selectedMonitor }: NewAlertParams) { const actions: AlertAction[] = []; defaultActions.forEach((aId) => { const action: AlertAction = { @@ -40,27 +52,52 @@ export function populateAlertActions({ defaultActions, monitorId, monitorName }: group: MONITOR_STATUS.id, params: {}, }; + + const recoveredAction: AlertAction = { + id: aId.id, + actionTypeId: aId.actionTypeId, + group: 'recovered', + params: { + message: getRecoveryMessage(selectedMonitor), + }, + }; + switch (aId.actionTypeId) { case PAGER_DUTY_ACTION_ID: - action.params = getPagerDutyActionParams(monitorId); + action.params = getPagerDutyActionParams(selectedMonitor); + recoveredAction.params = getPagerDutyActionParams(selectedMonitor, true); + actions.push(recoveredAction); break; case SERVER_LOG_ACTION_ID: - action.params = getServerLogActionParams(); + action.params = getServerLogActionParams(selectedMonitor); + recoveredAction.params = getServerLogActionParams(selectedMonitor, true); + actions.push(recoveredAction); break; case INDEX_ACTION_ID: - action.params = getIndexActionParams(); + action.params = getIndexActionParams(selectedMonitor); + recoveredAction.params = getIndexActionParams(selectedMonitor, true); + actions.push(recoveredAction); break; case SERVICE_NOW_ACTION_ID: action.params = getServiceNowActionParams(); + // Recovery action for service now is not implemented yet break; case JIRA_ACTION_ID: action.params = getJiraActionParams(); + // Recovery action for Jira is not implemented yet break; case WEBHOOK_ACTION_ID: - action.params = getWebhookActionParams(); + action.params = getWebhookActionParams(selectedMonitor); + recoveredAction.params = getWebhookActionParams(selectedMonitor, true); + actions.push(recoveredAction); break; case SLACK_ACTION_ID: case TEAMS_ACTION_ID: + action.params = { + message: MonitorStatusTranslations.defaultActionMessage, + }; + actions.push(recoveredAction); + break; default: action.params = { message: MonitorStatusTranslations.defaultActionMessage, @@ -73,7 +110,21 @@ export function populateAlertActions({ defaultActions, monitorId, monitorName }: return actions; } -function getIndexActionParams(): IndexActionParams { +function getIndexActionParams(selectedMonitor: Ping, recovery = false): IndexActionParams { + if (recovery) { + return { + documents: [ + { + monitorName: '{{state.monitorName}}', + monitorUrl: '{{{state.monitorUrl}}}', + statusMessage: getRecoveryMessage(selectedMonitor), + latestErrorMessage: '', + observerLocation: '{{state.observerLocation}}', + }, + ], + indexOverride: null, + }; + } return { documents: [ { @@ -88,22 +139,37 @@ function getIndexActionParams(): IndexActionParams { }; } -function getServerLogActionParams(): ServerLogActionParams { +function getServerLogActionParams(selectedMonitor: Ping, recovery = false): ServerLogActionParams { + if (recovery) { + return { + level: 'info', + message: getRecoveryMessage(selectedMonitor), + }; + } return { level: 'warn', message: MonitorStatusTranslations.defaultActionMessage, }; } -function getWebhookActionParams(): WebhookActionParams { +function getWebhookActionParams(selectedMonitor: Ping, recovery = false): WebhookActionParams { return { - body: MonitorStatusTranslations.defaultActionMessage, + body: recovery + ? getRecoveryMessage(selectedMonitor) + : MonitorStatusTranslations.defaultActionMessage, }; } -function getPagerDutyActionParams(monitorId: string): PagerDutyActionParams { +function getPagerDutyActionParams(selectedMonitor: Ping, recovery = false): PagerDutyActionParams { + if (recovery) { + return { + dedupKey: selectedMonitor.monitor.id + MONITOR_STATUS.id, + eventAction: 'resolve', + summary: getRecoveryMessage(selectedMonitor), + }; + } return { - dedupKey: monitorId + MONITOR_STATUS.id, + dedupKey: selectedMonitor.monitor.id + MONITOR_STATUS.id, eventAction: 'trigger', severity: 'error', summary: MonitorStatusTranslations.defaultActionMessage, diff --git a/x-pack/plugins/uptime/public/state/api/alerts.ts b/x-pack/plugins/uptime/public/state/api/alerts.ts index ae203797982de..5931936c48163 100644 --- a/x-pack/plugins/uptime/public/state/api/alerts.ts +++ b/x-pack/plugins/uptime/public/state/api/alerts.ts @@ -16,6 +16,7 @@ import { Alert, AlertTypeParams } from '../../../../alerting/common'; import { AtomicStatusCheckParams } from '../../../common/runtime_types/alerts'; import { populateAlertActions } from './alert_actions'; +import { Ping } from '../../../common/runtime_types/ping'; const UPTIME_AUTO_ALERT = 'UPTIME_AUTO'; @@ -24,8 +25,7 @@ export const fetchConnectors = async () => { }; export interface NewAlertParams extends AlertTypeParams { - monitorId: string; - monitorName?: string; + selectedMonitor: Ping; defaultActions: ActionConnector[]; } @@ -46,9 +46,12 @@ type NewMonitorStatusAlert = Omit< export const createAlert = async ({ defaultActions, monitorId, - monitorName, + selectedMonitor, }: NewAlertParams): Promise => { - const actions: AlertAction[] = populateAlertActions({ defaultActions, monitorId, monitorName }); + const actions: AlertAction[] = populateAlertActions({ + defaultActions, + selectedMonitor, + }); const data: NewMonitorStatusAlert = { actions, @@ -67,7 +70,7 @@ export const createAlert = async ({ schedule: { interval: '1m' }, notifyWhen: 'onActionGroupChange', tags: [UPTIME_AUTO_ALERT], - name: `${monitorName} (Simple status alert)`, + name: `${selectedMonitor?.monitor.name || selectedMonitor?.url?.full}(Simple status alert)`, enabled: true, throttle: null, }; diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts index f68c63a0eb435..6a69921a36671 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.ts @@ -264,7 +264,6 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( state, services: { alertInstanceFactory }, }, - dynamicSettings, uptimeEsClient, }) { const { @@ -283,9 +282,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory = ( const filterString = await formatFilterString(uptimeEsClient, filters, search, libs); const timerange = oldVersionTimeRange || { - from: isAutoGenerated - ? state.lastCheckedAt - : `now-${String(timerangeCount) + timerangeUnit}`, + from: `now-${String(timerangeCount) + timerangeUnit}`, to: 'now', }; diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts index 302fb14012ade..52e602989afd3 100644 --- a/x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/uptime/simple_down_alert.ts @@ -16,6 +16,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const uptimeService = getService('uptime'); const retry = getService('retry'); const supertest = getService('supertest'); + const toasts = getService('toasts'); const testSubjects = getService('testSubjects'); @@ -46,6 +47,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('displays to define default connector', async () => { + await testSubjects.click('uptimeDismissSyntheticsCallout'); await hideErrorToast(); await testSubjects.click('uptimeDisplayDefineConnector'); await testSubjects.existOrFail('uptimeSettingsDefineConnector'); @@ -71,6 +73,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('displays relevant alert in list drawer', async () => { + await toasts.dismissAllToasts(); + await testSubjects.click(`xpack.uptime.monitorList.${monitorId}.expandMonitorDetail`); await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('uptimeMonitorListDrawerAlert0'); @@ -87,31 +91,38 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { alert = alertsFromThisTest[0]; }); - const { actions, alertTypeId, consumer, id, tags } = alert ?? {}; - try { - expect(actions).to.eql([ - { - actionTypeId: '.slack', - group: 'xpack.uptime.alerts.actionGroups.monitorStatus', - id: 'my-slack1', - params: { - message: - 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', - }, + const { actions, alertTypeId, consumer, tags } = alert ?? {}; + expect(actions).to.eql([ + { + actionTypeId: '.slack', + group: 'recovered', + params: { + message: + 'Monitor 0000-intermittent with url http://localhost:5678/pattern?r=200x5,500x1 has recovered with status Up', }, - ]); - expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus'); - expect(consumer).to.eql('uptime'); - expect(tags).to.eql(['UPTIME_AUTO']); - } catch (e) { - await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204); - } + id: 'my-slack1', + }, + { + actionTypeId: '.slack', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + params: { + message: + 'Monitor {{state.monitorName}} with url {{{state.monitorUrl}}} is {{state.statusMessage}} from {{state.observerLocation}}. The latest error message is {{{state.latestErrorMessage}}}', + }, + id: 'my-slack1', + }, + ]); + expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus'); + expect(consumer).to.eql('uptime'); + expect(tags).to.eql(['UPTIME_AUTO']); }); it('disable simple status alert', async () => { await testSubjects.click('uptimeDisableSimpleDownAlert' + monitorId); await pageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('uptimeEnableSimpleDownAlert' + monitorId); + await retry.try(async () => { + await testSubjects.existOrFail('uptimeEnableSimpleDownAlert' + monitorId); + }); }); }); };