[Uptime] Fix Monitor status toggle alert receovery state (#89273)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Shahzad 2021-04-29 18:42:52 +02:00 committed by GitHub
parent 5f57766e03
commit 18213b673f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 337 additions and 246 deletions

View file

@ -89,10 +89,7 @@ export const MonitorPageTitle: React.FC = () => {
<EuiSpacer size="xs" />
</EuiFlexItem>
<EuiFlexItem grow={false} style={{ justifyContent: 'center' }}>
<EnableMonitorAlert
monitorId={monitorId}
monitorName={selectedMonitor?.monitor?.name || selectedMonitor?.url?.full}
/>
<EnableMonitorAlert monitorId={monitorId} selectedMonitor={selectedMonitor!} />
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="s" />

View file

@ -1,89 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EnableAlertComponent renders without errors for valid props 1`] = `
<div
class="euiPopover euiPopover--anchorDownCenter"
>
<div
class="euiPopover__anchor"
>
<div
class="euiSwitch euiSwitch--compressed"
>
<button
aria-checked="false"
aria-label="Enable status alert"
class="euiSwitch__button"
data-test-subj="uptimeDisplayDefineConnector"
id="defineAlertSettingsSwitch"
role="switch"
type="button"
>
<span
class="euiSwitch__body"
>
<span
class="euiSwitch__thumb"
/>
<span
class="euiSwitch__track"
/>
</span>
</button>
</div>
</div>
</div>
`;
exports[`EnableAlertComponent shallow renders without errors for valid props 1`] = `
<Provider
store={
Object {
"dispatch": [MockFunction],
"getState": [MockFunction],
"replaceReducer": [MockFunction],
"subscribe": [MockFunction],
}
}
>
<Router
history={
Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"push": [Function],
"replace": [Function],
}
}
>
<EnableMonitorAlert
monitorId="testMonitor"
monitorName="My website"
/>
</Router>
</Provider>
`;

View file

@ -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(
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
it('it displays define connectors when there is none', () => {
const { getByTestId, getByLabelText, getByText } = render(
<EnableMonitorAlert
monitorId={'testMonitor'}
selectedMonitor={makePing({ name: 'My website' })}
/>
);
expect(wrapper).toMatchSnapshot();
});
expect(getByTestId('uptimeDisplayDefineConnector'));
expect(getByLabelText(ENABLE_STATUS_ALERT));
it('renders without errors for valid props', () => {
const wrapper = renderWithRouterRedux(
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
);
expect(wrapper).toMatchSnapshot();
});
fireEvent.click(getByTestId('uptimeDisplayDefineConnector'));
it('displays define connectors when there is none', () => {
defaultConnectors = [];
const wrapper = mountWithRouterRedux(
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
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(`
<ReactRouterEuiLink
data-test-subj="uptimeSettingsLink"
to="/settings?focusConnectorField=true"
>
<ReactRouterHelperForEui
to="/settings?focusConnectorField=true"
>
<EuiLink
data-test-subj="uptimeSettingsLink"
href="/settings?focusConnectorField=true"
onClick={[Function]}
>
<a
className="euiLink euiLink--primary"
data-test-subj="uptimeSettingsLink"
href="/settings?focusConnectorField=true"
onClick={[Function]}
rel="noreferrer"
>
Settings
</a>
</EuiLink>
</ReactRouterHelperForEui>
</ReactRouterEuiLink>
`);
});
it('does not displays define connectors when there is connector', () => {
defaultConnectors = ['infra-slack-connector-id'];
const wrapper = mountWithRouterRedux(
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
const defaultConnectors = ['infra-slack-connector-id'];
const { getByTestId, getByLabelText } = render(
<EnableMonitorAlert
monitorId={'testMonitor'}
selectedMonitor={makePing({ name: 'My website' })}
/>,
{
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(
<EnableMonitorAlert monitorId={'testMonitor'} monitorName={'My website'} />
const { getByTestId, getByLabelText } = render(
<EnableMonitorAlert
monitorId={'testMonitor'}
selectedMonitor={makePing({ name: 'My website' })}
/>,
{
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));
});
});

View file

@ -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 ? (
<div className="eui-displayInlineBlock" style={{ marginRight: 10 }}>
{
<EuiToolTip content={btnLabel}>
<>
<EuiSwitch
id={'enableDisableAlertSwitch'}
compressed={!isMonitorPage}
disabled={showSpinner}
label={btnLabel}
showLabel={!!isMonitorPage}
aria-label={btnLabel}
onChange={onAlertClick}
checked={!!hasAlert}
data-test-subj={
hasAlert
? 'uptimeDisableSimpleDownAlert' + monitorId
: 'uptimeEnableSimpleDownAlert' + monitorId
}
/>{' '}
{showSpinner && <EuiLoadingSpinner className="eui-alignMiddle" />}
</>
</EuiToolTip>
}
<EuiToolTip content={btnLabel}>
<>
<EuiSwitch
id={'enableDisableAlertSwitch'}
compressed={!isMonitorPage}
disabled={showSpinner}
label={btnLabel}
showLabel={!!isMonitorPage}
aria-label={btnLabel}
onChange={onAlertClick}
checked={!!hasAlert}
data-test-subj={
hasAlert
? 'uptimeDisableSimpleDownAlert' + monitorId
: 'uptimeEnableSimpleDownAlert' + monitorId
}
/>{' '}
{showSpinner && <EuiLoadingSpinner className="eui-alignMiddle" />}
</>
</EuiToolTip>
</div>
) : (
<DefineAlertConnectors />

View file

@ -142,7 +142,7 @@ export const MonitorListComponent: ({
render: (item: MonitorSummary) => (
<EnableMonitorAlert
monitorId={item.monitor_id}
monitorName={item.state.monitor.name || item.monitor_id}
selectedMonitor={item.state.summaryPings[0]}
/>
),
},

View file

@ -55,6 +55,7 @@ describe('SyntheticsCallout', () => {
grow={false}
>
<EuiButtonEmpty
data-test-subj="uptimeDismissSyntheticsCallout"
onClick={[Function]}
>
<FormattedMessage
@ -115,6 +116,7 @@ describe('SyntheticsCallout', () => {
grow={false}
>
<EuiButtonEmpty
data-test-subj="uptimeDismissSyntheticsCallout"
onClick={[Function]}
>
<FormattedMessage

View file

@ -58,6 +58,7 @@ export const SyntheticsCallout = () => {
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj="uptimeDismissSyntheticsCallout"
onClick={() => {
if (shouldShow) {
hideSyntheticsCallout();

View file

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

View file

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

View file

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

View file

@ -264,7 +264,6 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
state,
services: { alertInstanceFactory },
},
dynamicSettings,
uptimeEsClient,
}) {
const {
@ -283,9 +282,7 @@ export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
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',
};

View file

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