fixed tests
This commit is contained in:
parent
01c7c7d2aa
commit
e9f2cd05bd
|
@ -5,25 +5,33 @@
|
|||
*/
|
||||
|
||||
import uuid from 'uuid';
|
||||
import { range } from 'lodash';
|
||||
import { range, random, pick } from 'lodash';
|
||||
import { AlertType } from '../../../../plugins/alerts/server';
|
||||
import { DEFAULT_INSTANCES_TO_GENERATE, ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
||||
|
||||
const ACTION_GROUPS = [
|
||||
{ id: 'small', name: 'small', tshirtSize: 1 },
|
||||
{ id: 'medium', name: 'medium', tshirtSize: 2 },
|
||||
{ id: 'large', name: 'large', tshirtSize: 3 },
|
||||
];
|
||||
|
||||
export const alertType: AlertType = {
|
||||
id: 'example.always-firing',
|
||||
name: 'Always firing',
|
||||
actionGroups: [{ id: 'default', name: 'default' }],
|
||||
defaultActionGroupId: 'default',
|
||||
actionGroups: ACTION_GROUPS.map((actionGroup) => pick(actionGroup, ['id', 'name'])),
|
||||
defaultActionGroupId: 'small',
|
||||
async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE }, state }) {
|
||||
const count = (state.count ?? 0) + 1;
|
||||
|
||||
range(instances)
|
||||
.map(() => ({ id: uuid.v4() }))
|
||||
.forEach((instance: { id: string }) => {
|
||||
.map(() => ({ id: uuid.v4(), tshirtSize: random(1, 3) }))
|
||||
.forEach((instance: { id: string; tshirtSize: number }) => {
|
||||
services
|
||||
.alertInstanceFactory(instance.id)
|
||||
.replaceState({ triggerdOnCycle: count })
|
||||
.scheduleActions('default');
|
||||
.scheduleActions(
|
||||
ACTION_GROUPS.find((actionGroup) => actionGroup.tshirtSize === instance.tshirtSize)!.id
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
export { NonEmptyString } from './detection_engine/schemas/types/non_empty_string';
|
||||
export { DefaultArray } from './detection_engine/schemas/types/default_array';
|
||||
export { DefaultUuid } from './detection_engine/schemas/types/default_uuid';
|
||||
export { siemRuleActionGroups } from './detection_engine/signals/siem_rule_action_groups';
|
||||
export { DefaultStringArray } from './detection_engine/schemas/types/default_string_array';
|
||||
export {
|
||||
DefaultVersionNumber,
|
||||
|
|
|
@ -21,10 +21,11 @@ import {
|
|||
import { AlertAction } from '../../../../../../alerts/common';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { FORM_ERRORS_TITLE } from './translations';
|
||||
import { siemRuleActionGroups } from '../../../../../common';
|
||||
|
||||
type ThrottleSelectField = typeof SelectField;
|
||||
|
||||
const DEFAULT_ACTION_GROUP_ID = 'default';
|
||||
const DEFAULT_ACTION_GROUP = siemRuleActionGroups[0];
|
||||
const DEFAULT_ACTION_MESSAGE =
|
||||
'Rule {{context.rule.name}} generated {{state.signals_count}} alerts';
|
||||
|
||||
|
@ -52,12 +53,19 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables
|
|||
[field.value]
|
||||
);
|
||||
|
||||
const setActionPropByIndex = (prop: 'id' | 'group', value: string, index: number) => {
|
||||
const updatedActions = [...(actions as Array<Partial<AlertAction>>)];
|
||||
updatedActions[index] = deepMerge(updatedActions[index], { [prop]: value });
|
||||
field.setValue(updatedActions);
|
||||
};
|
||||
const setActionIdByIndex = useCallback(
|
||||
(id: string, index: number) => {
|
||||
const updatedActions = [...(actions as Array<Partial<AlertAction>>)];
|
||||
updatedActions[index] = deepMerge(updatedActions[index], { id });
|
||||
field.setValue(updatedActions);
|
||||
},
|
||||
(id: string, index: number) => setActionPropByIndex('id', id, index),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[field.setValue, actions]
|
||||
);
|
||||
|
||||
const setActionGroupIdByIndex = useCallback(
|
||||
(group: string, index: number) => setActionPropByIndex('group', group, index),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[field.setValue, actions]
|
||||
);
|
||||
|
@ -118,7 +126,9 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables
|
|||
docLinks={docLinks}
|
||||
capabilities={capabilities}
|
||||
messageVariables={messageVariables}
|
||||
defaultActionGroupId={DEFAULT_ACTION_GROUP_ID}
|
||||
defaultActionGroupId={DEFAULT_ACTION_GROUP.id}
|
||||
actionGroups={siemRuleActionGroups}
|
||||
setActionGroupIdByIndex={setActionGroupIdByIndex}
|
||||
setActionIdByIndex={setActionIdByIndex}
|
||||
setAlertProperty={setAlertProperty}
|
||||
setActionParamsProperty={setActionParamsProperty}
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
import { Logger } from 'src/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { NOTIFICATIONS_ID, SERVER_APP_ID } from '../../../../common/constants';
|
||||
import { siemRuleActionGroups } from '../../../../common';
|
||||
|
||||
import { NotificationAlertTypeDefinition } from './types';
|
||||
import { getSignalsCount } from './get_signals_count';
|
||||
import { RuleAlertAttributes } from '../signals/types';
|
||||
import { siemRuleActionGroups } from '../signals/siem_rule_action_groups';
|
||||
import { scheduleNotificationActions } from './schedule_notification_actions';
|
||||
import { getNotificationResultsLink } from './utils';
|
||||
import { parseScheduleDates } from '../../../../common/detection_engine/parse_schedule_dates';
|
||||
|
|
|
@ -43,7 +43,7 @@ import {
|
|||
createSearchAfterReturnTypeFromResponse,
|
||||
} from './utils';
|
||||
import { signalParamsSchema } from './signal_params_schema';
|
||||
import { siemRuleActionGroups } from './siem_rule_action_groups';
|
||||
import { siemRuleActionGroups } from '../../../../common';
|
||||
import { findMlSignals } from './find_ml_signals';
|
||||
import { findThresholdSignals } from './find_threshold_signals';
|
||||
import { bulkCreateMlSignals } from './bulk_create_ml_signals';
|
||||
|
|
|
@ -112,8 +112,6 @@ describe('action_form', () => {
|
|||
};
|
||||
|
||||
describe('action_form in alert', () => {
|
||||
let wrapper: ReactWrapper<any>;
|
||||
|
||||
async function setup(customActions?: AlertAction[]) {
|
||||
const { loadAllActions } = jest.requireMock('../../lib/action_connector_api');
|
||||
loadAllActions.mockResolvedValueOnce([
|
||||
|
@ -217,7 +215,7 @@ describe('action_form', () => {
|
|||
mutedInstanceIds: [],
|
||||
} as unknown) as Alert;
|
||||
|
||||
wrapper = mountWithIntl(
|
||||
const wrapper = mountWithIntl(
|
||||
<ActionForm
|
||||
actions={initialAlert.actions}
|
||||
messageVariables={[
|
||||
|
@ -228,6 +226,10 @@ describe('action_form', () => {
|
|||
setActionIdByIndex={(id: string, index: number) => {
|
||||
initialAlert.actions[index].id = id;
|
||||
}}
|
||||
actionGroups={[{ id: 'default', name: 'Default' }]}
|
||||
setActionGroupIdByIndex={(group: string, index: number) => {
|
||||
initialAlert.actions[index].group = group;
|
||||
}}
|
||||
setAlertProperty={(_updatedActions: AlertAction[]) => {}}
|
||||
setActionParamsProperty={(key: string, value: any, index: number) =>
|
||||
(initialAlert.actions[index] = { ...initialAlert.actions[index], [key]: value })
|
||||
|
@ -297,13 +299,16 @@ describe('action_form', () => {
|
|||
await nextTick();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
it('renders available action cards', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
`[data-test-subj="${actionType.id}-ActionTypeSelectOption"]`
|
||||
);
|
||||
wrapper.debug();
|
||||
expect(actionOption.exists()).toBeTruthy();
|
||||
expect(
|
||||
wrapper
|
||||
|
@ -314,7 +319,7 @@ describe('action_form', () => {
|
|||
});
|
||||
|
||||
it('does not render action types disabled by config', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
'[data-test-subj="disabled-by-config-ActionTypeSelectOption"]'
|
||||
);
|
||||
|
@ -322,52 +327,72 @@ describe('action_form', () => {
|
|||
});
|
||||
|
||||
it('render action types which is preconfigured only (disabled by config and with preconfigured connectors)', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]');
|
||||
expect(actionOption.exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders available action groups for the selected action type', async () => {
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
`[data-test-subj="${actionType.id}-ActionTypeSelectOption"]`
|
||||
);
|
||||
actionOption.first().simulate('click');
|
||||
const actionGroupsSelect = wrapper.find(
|
||||
`[data-test-subj="addNewActionConnectorActionGroup-0"]`
|
||||
);
|
||||
expect((actionGroupsSelect.first().props() as any).options).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"data-test-subj": "addNewActionConnectorActionGroup-0-option-default",
|
||||
"inputDisplay": "Default",
|
||||
"value": "default",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('renders available connectors for the selected action type', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
`[data-test-subj="${actionType.id}-ActionTypeSelectOption"]`
|
||||
);
|
||||
actionOption.first().simulate('click');
|
||||
const combobox = wrapper.find(`[data-test-subj="selectActionConnector-${actionType.id}"]`);
|
||||
expect((combobox.first().props() as any).options).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"id": "test",
|
||||
"key": "test",
|
||||
"label": "Test connector ",
|
||||
},
|
||||
Object {
|
||||
"id": "test2",
|
||||
"key": "test2",
|
||||
"label": "Test connector 2 (preconfigured)",
|
||||
},
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
Object {
|
||||
"id": "test",
|
||||
"key": "test",
|
||||
"label": "Test connector ",
|
||||
},
|
||||
Object {
|
||||
"id": "test2",
|
||||
"key": "test2",
|
||||
"label": "Test connector 2 (preconfigured)",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('renders only preconfigured connectors for the selected preconfigured action type', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]');
|
||||
actionOption.first().simulate('click');
|
||||
const combobox = wrapper.find('[data-test-subj="selectActionConnector-preconfigured"]');
|
||||
expect((combobox.first().props() as any).options).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"id": "test3",
|
||||
"key": "test3",
|
||||
"label": "Preconfigured Only (preconfigured)",
|
||||
},
|
||||
]
|
||||
`);
|
||||
Array [
|
||||
Object {
|
||||
"id": "test3",
|
||||
"key": "test3",
|
||||
"label": "Preconfigured Only (preconfigured)",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('does not render "Add connector" button for preconfigured only action type', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find('[data-test-subj="preconfigured-ActionTypeSelectOption"]');
|
||||
actionOption.first().simulate('click');
|
||||
const preconfigPannel = wrapper.find('[data-test-subj="alertActionAccordion-default"]');
|
||||
|
@ -378,7 +403,7 @@ describe('action_form', () => {
|
|||
});
|
||||
|
||||
it('renders action types disabled by license', async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
'[data-test-subj="disabled-by-license-ActionTypeSelectOption"]'
|
||||
);
|
||||
|
@ -391,7 +416,7 @@ describe('action_form', () => {
|
|||
});
|
||||
|
||||
it(`shouldn't render action types without params component`, async () => {
|
||||
await setup();
|
||||
const wrapper = await setup();
|
||||
const actionOption = wrapper.find(
|
||||
`[data-test-subj="${actionTypeWithoutParams.id}-ActionTypeSelectOption"]`
|
||||
);
|
||||
|
|
|
@ -102,7 +102,7 @@ export const ActionForm = ({
|
|||
const [activeActionItem, setActiveActionItem] = useState<ActiveActionConnectorState | undefined>(
|
||||
undefined
|
||||
);
|
||||
const [isAddActionPanelOpen, setIsAddActionPanelOpen] = useState<boolean>(actions.length === 0);
|
||||
const [isAddActionPanelOpen, setIsAddActionPanelOpen] = useState<boolean>(true);
|
||||
const [connectors, setConnectors] = useState<ActionConnector[]>([]);
|
||||
const [isLoadingConnectors, setIsLoadingConnectors] = useState<boolean>(false);
|
||||
const [isLoadingActionTypes, setIsLoadingActionTypes] = useState<boolean>(false);
|
||||
|
@ -341,7 +341,7 @@ export const ActionForm = ({
|
|||
singleSelection={{ asPlainText: true }}
|
||||
options={optionsList}
|
||||
id={`selectActionConnector-${actionItem.id}`}
|
||||
data-test-subj={`selectActionConnector-${index}`}
|
||||
data-test-subj={`selectActionConnector-${actionItem.actionTypeId}`}
|
||||
selectedOptions={getSelectedOptions(actionItem.id)}
|
||||
onChange={(selectedOptions) => {
|
||||
setActionIdByIndex(selectedOptions[0].id ?? '', index);
|
||||
|
|
Loading…
Reference in a new issue