Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,24 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<IndexThr
}
);

const setDefaultExpressionValues = () => {
const setDefaultExpressionValues = async () => {
setAlertProperty('params', {
aggType: DEFAULT_VALUES.AGGREGATION_TYPE,
termSize: DEFAULT_VALUES.TERM_SIZE,
thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR,
timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE,
timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT,
groupBy: DEFAULT_VALUES.GROUP_BY,
threshold: DEFAULT_VALUES.THRESHOLD,
...alertParams,
aggType: aggType ?? DEFAULT_VALUES.AGGREGATION_TYPE,
termSize: termSize ?? DEFAULT_VALUES.TERM_SIZE,
thresholdComparator: thresholdComparator ?? DEFAULT_VALUES.THRESHOLD_COMPARATOR,
timeWindowSize: timeWindowSize ?? DEFAULT_VALUES.TIME_WINDOW_SIZE,
timeWindowUnit: timeWindowUnit ?? DEFAULT_VALUES.TIME_WINDOW_UNIT,
groupBy: groupBy ?? DEFAULT_VALUES.GROUP_BY,
threshold: threshold ?? DEFAULT_VALUES.THRESHOLD,
});
if (index.length > 0) {
const currentEsFields = await getFields(index);
const timeFields = getTimeFieldOptions(currentEsFields as any);

setEsFields(currentEsFields);
setTimeFieldOptions([firstFieldOption, ...timeFields]);
}
};

const getFields = async (indexes: string[]) => {
Expand Down Expand Up @@ -258,7 +266,17 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent<IndexThr
// reset time field and expression fields if indices are deleted
if (indices.length === 0) {
setTimeFieldOptions([firstFieldOption]);
setDefaultExpressionValues();
setAlertProperty('params', {
...alertParams,
index: indices,
aggType: DEFAULT_VALUES.AGGREGATION_TYPE,
termSize: DEFAULT_VALUES.TERM_SIZE,
thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR,
timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE,
timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT,
groupBy: DEFAULT_VALUES.GROUP_BY,
threshold: DEFAULT_VALUES.THRESHOLD,
});
return;
}
const currentEsFields = await getFields(indices);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { TypeRegistry } from '../type_registry';
import { AlertTypeModel, ActionTypeModel } from '../../types';

export interface AlertsContextValue {
addFlyoutVisible: boolean;
setAddFlyoutVisibility: React.Dispatch<React.SetStateAction<boolean>>;
reloadAlerts?: () => Promise<void>;
http: HttpSetup;
alertTypeRegistry: TypeRegistry<AlertTypeModel>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ describe('updateAlert', () => {
Array [
"/api/alert/123",
Object {
"body": "{\\"throttle\\":\\"1m\\",\\"consumer\\":\\"alerting\\",\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"schedule\\":{\\"interval\\":\\"1m\\"},\\"params\\":{},\\"actions\\":[],\\"createdAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"updatedAt\\":\\"1970-01-01T00:00:00.000Z\\",\\"apiKey\\":null,\\"apiKeyOwner\\":null}",
"body": "{\\"throttle\\":\\"1m\\",\\"name\\":\\"test\\",\\"tags\\":[\\"foo\\"],\\"schedule\\":{\\"interval\\":\\"1m\\"},\\"params\\":{},\\"actions\\":[]}",
},
]
`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HttpSetup } from 'kibana/public';
import * as t from 'io-ts';
import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either';
import { pick } from 'lodash';
import { alertStateSchema } from '../../../../alerting/common';
import { BASE_ALERT_API_PATH } from '../constants';
import { Alert, AlertType, AlertWithoutId, AlertTaskState } from '../../types';
Expand Down Expand Up @@ -126,7 +127,9 @@ export async function updateAlert({
id: string;
}): Promise<Alert> {
return await http.put(`${BASE_ALERT_API_PATH}/${id}`, {
body: JSON.stringify(alert),
body: JSON.stringify(
pick(alert, ['throttle', 'name', 'tags', 'schedule', 'params', 'actions'])
),
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ describe('alert_add', () => {
wrapper = mountWithIntl(
<AlertsContextProvider
value={{
addFlyoutVisible: true,
setAddFlyoutVisibility: state => {},
reloadAlerts: () => {
return new Promise<void>(() => {});
},
Expand All @@ -81,7 +79,11 @@ describe('alert_add', () => {
uiSettings: deps.uiSettings,
}}
>
<AlertAdd consumer={'alerting'} />
<AlertAdd
consumer={'alerting'}
addFlyoutVisible={true}
setAddFlyoutVisibility={state => {}}
/>
</AlertsContextProvider>
);
// Wait for active space to resolve before requesting the component to update
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ import { createAlert } from '../../lib/alert_api';

interface AlertAddProps {
consumer: string;
addFlyoutVisible: boolean;
setAddFlyoutVisibility: React.Dispatch<React.SetStateAction<boolean>>;
alertTypeId?: string;
canChangeTrigger?: boolean;
}

export const AlertAdd = ({ consumer, canChangeTrigger, alertTypeId }: AlertAddProps) => {
export const AlertAdd = ({
consumer,
addFlyoutVisible,
setAddFlyoutVisibility,
canChangeTrigger,
alertTypeId,
}: AlertAddProps) => {
const initialAlert = ({
params: {},
consumer,
Expand All @@ -51,8 +59,6 @@ export const AlertAdd = ({ consumer, canChangeTrigger, alertTypeId }: AlertAddPr
};

const {
addFlyoutVisible,
setAddFlyoutVisibility,
reloadAlerts,
http,
toastNotifications,
Expand All @@ -74,7 +80,7 @@ export const AlertAdd = ({ consumer, canChangeTrigger, alertTypeId }: AlertAddPr
return null;
}

const alertType = alertTypeRegistry.get(alert.alertTypeId);
const alertType = alert.alertTypeId ? alertTypeRegistry.get(alert.alertTypeId) : null;
const errors = {
...(alertType ? alertType.validate(alert.params).errors : []),
...validateBaseProperties(alert).errors,
Expand Down Expand Up @@ -106,7 +112,7 @@ export const AlertAdd = ({ consumer, canChangeTrigger, alertTypeId }: AlertAddPr
const newAlert = await createAlert({ http, alert });
if (toastNotifications) {
toastNotifications.addSuccess(
i18n.translate('xpack.triggersActionsUI.sections.alertForm.saveSuccessNotificationText', {
i18n.translate('xpack.triggersActionsUI.sections.alertAdd.saveSuccessNotificationText', {
defaultMessage: "Saved '{alertName}'",
values: {
alertName: newAlert.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* 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 * as React from 'react';
import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers';
import { act } from 'react-dom/test-utils';
import { coreMock } from '../../../../../../../src/core/public/mocks';
import { actionTypeRegistryMock } from '../../action_type_registry.mock';
import { ValidationResult } from '../../../types';
import { AlertsContextProvider } from '../../context/alerts_context';
import { alertTypeRegistryMock } from '../../alert_type_registry.mock';
import { ReactWrapper } from 'enzyme';
import { AlertEdit } from './alert_edit';
const actionTypeRegistry = actionTypeRegistryMock.create();
const alertTypeRegistry = alertTypeRegistryMock.create();

describe('alert_edit', () => {
let deps: any;
let wrapper: ReactWrapper<any>;

beforeAll(async () => {
const mockes = coreMock.createSetup();
deps = {
toastNotifications: mockes.notifications.toasts,
http: mockes.http,
uiSettings: mockes.uiSettings,
actionTypeRegistry: actionTypeRegistry as any,
alertTypeRegistry: alertTypeRegistry as any,
};
const alertType = {
id: 'my-alert-type',
iconClass: 'test',
name: 'test-alert',
validate: (): ValidationResult => {
return { errors: {} };
},
alertParamsExpression: () => <React.Fragment />,
};

const actionTypeModel = {
id: 'my-action-type',
iconClass: 'test',
selectMessage: 'test',
validateConnector: (): ValidationResult => {
return { errors: {} };
},
validateParams: (): ValidationResult => {
const validationResult = { errors: {} };
return validationResult;
},
actionConnectorFields: null,
actionParamsFields: null,
};

const alert = {
id: 'ab5661e0-197e-45ee-b477-302d89193b5e',
params: {
aggType: 'average',
threshold: [1000, 5000],
index: 'kibana_sample_data_flights',
timeField: 'timestamp',
aggField: 'DistanceMiles',
window: '1s',
comparator: 'between',
},
consumer: 'alerting',
alertTypeId: 'my-alert-type',
enabled: false,
schedule: { interval: '1m' },
actions: [
{
actionTypeId: 'my-action-type',
group: 'threshold met',
params: { message: 'Alert [{{ctx.metadata.name}}] has exceeded the threshold' },
message: 'Alert [{{ctx.metadata.name}}] has exceeded the threshold',
id: '917f5d41-fbc4-4056-a8ad-ac592f7dcee2',
},
],
tags: [],
name: 'test alert',
throttle: null,
apiKeyOwner: null,
createdBy: 'elastic',
updatedBy: 'elastic',
createdAt: new Date(),
muteAll: false,
mutedInstanceIds: [],
updatedAt: new Date(),
};
actionTypeRegistry.get.mockReturnValueOnce(actionTypeModel);
actionTypeRegistry.has.mockReturnValue(true);
alertTypeRegistry.list.mockReturnValue([alertType]);
alertTypeRegistry.get.mockReturnValue(alertType);
alertTypeRegistry.has.mockReturnValue(true);
actionTypeRegistry.list.mockReturnValue([actionTypeModel]);
actionTypeRegistry.has.mockReturnValue(true);

wrapper = mountWithIntl(
<AlertsContextProvider
value={{
reloadAlerts: () => {
return new Promise<void>(() => {});
},
http: deps!.http,
actionTypeRegistry: deps!.actionTypeRegistry,
alertTypeRegistry: deps!.alertTypeRegistry,
toastNotifications: deps!.toastNotifications,
uiSettings: deps!.uiSettings,
}}
>
<AlertEdit
editFlyoutVisible={true}
setEditFlyoutVisibility={() => {}}
initialAlert={alert}
/>
</AlertsContextProvider>
);
// Wait for active space to resolve before requesting the component to update
await act(async () => {
await nextTick();
wrapper.update();
});
});

it('renders alert add flyout', () => {
expect(wrapper.find('[data-test-subj="editAlertFlyoutTitle"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="saveEditedAlertButton"]').exists()).toBeTruthy();
});
});
Loading