Skip to content

Commit

Permalink
added alert services mock and use it in siem
Browse files Browse the repository at this point in the history
  • Loading branch information
gmmorris committed Apr 14, 2020
1 parent c2f2a79 commit d2265d9
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { savedObjectsClientMock } from 'src/core/server/mocks';
import { loggerMock } from 'src/core/server/logging/logger.mock';
import { getResult } from '../routes/__mocks__/request_responses';
import { rulesNotificationAlertType } from './rules_notification_alert_type';
import { buildSignalsSearchQuery } from './build_signals_query';
import { AlertInstance } from '../../../../../../../plugins/alerting/server';
import { alertsMock, AlertServicesMock } from '../../../../../../../plugins/alerting/server/mocks';
import { NotificationExecutorOptions } from './types';
jest.mock('./build_signals_query');

describe('rules_notification_alert_type', () => {
let payload: NotificationExecutorOptions;
let alert: ReturnType<typeof rulesNotificationAlertType>;
let alertInstanceMock: Record<string, jest.Mock>;
let alertInstanceFactoryMock: () => AlertInstance;
let savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
let logger: ReturnType<typeof loggerMock.create>;
let callClusterMock: jest.Mock;
let alertServices: AlertServicesMock;

beforeEach(() => {
alertInstanceMock = {
scheduleActions: jest.fn(),
replaceState: jest.fn(),
};
alertInstanceMock.replaceState.mockReturnValue(alertInstanceMock);
alertInstanceFactoryMock = jest.fn().mockReturnValue(alertInstanceMock);
callClusterMock = jest.fn();
savedObjectsClient = savedObjectsClientMock.create();
alertServices = alertsMock.createAlertServices();
logger = loggerMock.create();

payload = {
alertId: '1111',
services: {
savedObjectsClient,
alertInstanceFactory: alertInstanceFactoryMock,
callCluster: callClusterMock,
},
services: alertServices,
params: { ruleAlertId: '2222' },
state: {},
spaceId: '',
Expand All @@ -58,7 +43,7 @@ describe('rules_notification_alert_type', () => {

describe('executor', () => {
it('throws an error if rule alert was not found', async () => {
savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
attributes: {},
type: 'type',
Expand All @@ -72,13 +57,13 @@ describe('rules_notification_alert_type', () => {

it('should call buildSignalsSearchQuery with proper params', async () => {
const ruleAlert = getResult();
savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
attributes: ruleAlert,
});
callClusterMock.mockResolvedValue({
alertServices.callCluster.mockResolvedValue({
count: 0,
});

Expand All @@ -96,36 +81,38 @@ describe('rules_notification_alert_type', () => {

it('should not call alertInstanceFactory if signalsCount was 0', async () => {
const ruleAlert = getResult();
savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
attributes: ruleAlert,
});
callClusterMock.mockResolvedValue({
alertServices.callCluster.mockResolvedValue({
count: 0,
});

await alert.executor(payload);

expect(alertInstanceFactoryMock).not.toHaveBeenCalled();
expect(alertServices.alertInstanceFactory).not.toHaveBeenCalled();
});

it('should call scheduleActions if signalsCount was greater than 0', async () => {
const ruleAlert = getResult();
savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
attributes: ruleAlert,
});
callClusterMock.mockResolvedValue({
alertServices.callCluster.mockResolvedValue({
count: 10,
});

await alert.executor(payload);

expect(alertInstanceFactoryMock).toHaveBeenCalled();
expect(alertServices.alertInstanceFactory).toHaveBeenCalled();

const [{ value: alertInstanceMock }] = alertServices.alertInstanceFactory.mock.results;
expect(alertInstanceMock.replaceState).toHaveBeenCalledWith(
expect.objectContaining({ signals_count: 10 })
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
*/

import moment from 'moment';
import { savedObjectsClientMock } from 'src/core/server/mocks';
import { loggerMock } from 'src/core/server/logging/logger.mock';
import { getResult, getMlResult } from '../routes/__mocks__/request_responses';
import { signalRulesAlertType } from './signal_rule_alert_type';
import { AlertInstance } from '../../../../../../../plugins/alerting/server';
import { alertsMock, AlertServicesMock } from '../../../../../../../plugins/alerting/server/mocks';
import { ruleStatusServiceFactory } from './rule_status_service';
import { getGapBetweenRuns } from './utils';
import { RuleExecutorOptions } from './types';
Expand All @@ -28,18 +27,9 @@ jest.mock('../notifications/schedule_notification_actions');
jest.mock('./find_ml_signals');
jest.mock('./bulk_create_ml_signals');

const getPayload = (
ruleAlert: RuleAlertType,
alertInstanceFactoryMock: () => AlertInstance,
savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>,
callClusterMock: jest.Mock
) => ({
const getPayload = (ruleAlert: RuleAlertType, services: AlertServicesMock) => ({
alertId: ruleAlert.id,
services: {
savedObjectsClient,
alertInstanceFactory: alertInstanceFactoryMock,
callCluster: callClusterMock,
},
services,
params: {
...ruleAlert.params,
actions: [],
Expand Down Expand Up @@ -78,24 +68,14 @@ describe('rules_notification_alert_type', () => {
modulesProvider: jest.fn(),
resultsServiceProvider: jest.fn(),
};
let payload: RuleExecutorOptions;
let payload: jest.Mocked<RuleExecutorOptions>;
let alert: ReturnType<typeof signalRulesAlertType>;
let alertInstanceMock: Record<string, jest.Mock>;
let alertInstanceFactoryMock: () => AlertInstance;
let savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
let logger: ReturnType<typeof loggerMock.create>;
let callClusterMock: jest.Mock;
let alertServices: AlertServicesMock;
let ruleStatusService: Record<string, jest.Mock>;

beforeEach(() => {
alertInstanceMock = {
scheduleActions: jest.fn(),
replaceState: jest.fn(),
};
alertInstanceMock.replaceState.mockReturnValue(alertInstanceMock);
alertInstanceFactoryMock = jest.fn().mockReturnValue(alertInstanceMock);
callClusterMock = jest.fn();
savedObjectsClient = savedObjectsClientMock.create();
alertServices = alertsMock.createAlertServices();
logger = loggerMock.create();
ruleStatusService = {
success: jest.fn(),
Expand All @@ -111,20 +91,20 @@ describe('rules_notification_alert_type', () => {
searchAfterTimes: [],
createdSignalsCount: 10,
});
callClusterMock.mockResolvedValue({
alertServices.callCluster.mockResolvedValue({
hits: {
total: { value: 10 },
},
});
const ruleAlert = getResult();
savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
attributes: ruleAlert,
});

payload = getPayload(ruleAlert, alertInstanceFactoryMock, savedObjectsClient, callClusterMock);
payload = getPayload(ruleAlert, alertServices);

alert = signalRulesAlertType({
logger,
Expand Down Expand Up @@ -164,7 +144,7 @@ describe('rules_notification_alert_type', () => {
},
];

savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
Expand Down Expand Up @@ -195,7 +175,7 @@ describe('rules_notification_alert_type', () => {
},
];

savedObjectsClient.get.mockResolvedValue({
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
Expand All @@ -214,12 +194,7 @@ describe('rules_notification_alert_type', () => {
describe('ML rule', () => {
it('should throw an error if ML plugin was not available', async () => {
const ruleAlert = getMlResult();
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
alert = signalRulesAlertType({
logger,
version,
Expand All @@ -235,12 +210,7 @@ describe('rules_notification_alert_type', () => {
it('should throw an error if machineLearningJobId or anomalyThreshold was not null', async () => {
const ruleAlert = getMlResult();
ruleAlert.params.anomalyThreshold = undefined;
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
await alert.executor(payload);
expect(logger.error).toHaveBeenCalled();
expect(logger.error.mock.calls[0][0]).toContain(
Expand All @@ -250,12 +220,7 @@ describe('rules_notification_alert_type', () => {

it('should throw an error if Machine learning job summary was null', async () => {
const ruleAlert = getMlResult();
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
jobsSummaryMock.mockResolvedValue([]);
await alert.executor(payload);
expect(logger.warn).toHaveBeenCalled();
Expand All @@ -268,12 +233,7 @@ describe('rules_notification_alert_type', () => {

it('should log an error if Machine learning job was not started', async () => {
const ruleAlert = getMlResult();
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
jobsSummaryMock.mockResolvedValue([
{
id: 'some_job_id',
Expand All @@ -297,12 +257,7 @@ describe('rules_notification_alert_type', () => {

it('should not call ruleStatusService.success if no anomalies were found', async () => {
const ruleAlert = getMlResult();
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
jobsSummaryMock.mockResolvedValue([]);
(findMlSignals as jest.Mock).mockResolvedValue({
hits: {
Expand All @@ -320,12 +275,7 @@ describe('rules_notification_alert_type', () => {

it('should call ruleStatusService.success if signals were created', async () => {
const ruleAlert = getMlResult();
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
payload = getPayload(ruleAlert, alertServices);
jobsSummaryMock.mockResolvedValue([
{
id: 'some_job_id',
Expand Down Expand Up @@ -360,13 +310,8 @@ describe('rules_notification_alert_type', () => {
id: '99403909-ca9b-49ba-9d7a-7e5320e68d05',
},
];
payload = getPayload(
ruleAlert,
alertInstanceFactoryMock,
savedObjectsClient,
callClusterMock
);
savedObjectsClient.get.mockResolvedValue({
payload = getPayload(ruleAlert, alertServices);
alertServices.savedObjectsClient.get.mockResolvedValue({
id: 'id',
type: 'type',
references: [],
Expand Down
41 changes: 41 additions & 0 deletions x-pack/plugins/alerting/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import { alertsClientMock } from './alerts_client.mock';
import { PluginSetupContract, PluginStartContract } from './plugin';
import { savedObjectsClientMock } from '../../../../src/core/server/mocks';
import { createScopedSeachApiMock } from '../../../../src/plugins/data/server/mocks';
import { AlertInstance } from './alert_instance';

export { alertsClientMock };

Expand All @@ -24,7 +27,45 @@ const createStartMock = () => {
return mock;
};

const createAlertInstanceFactoryMock = () => {
const mock = {
hasScheduledActions: jest.fn(),
isThrottled: jest.fn(),
getScheduledActionOptions: jest.fn(),
unscheduleActions: jest.fn(),
getState: jest.fn(),
scheduleActions: jest.fn(),
replaceState: jest.fn(),
updateLastScheduledActions: jest.fn(),
toJSON: jest.fn(),
toRaw: jest.fn(),
};

// support chaining
mock.replaceState.mockReturnValue(mock);
mock.unscheduleActions.mockReturnValue(mock);
mock.scheduleActions.mockReturnValue(mock);

return (mock as unknown) as jest.Mocked<AlertInstance>;
};

const createAlertServicesMock = () => {
const alertInstanceFactoryMock = createAlertInstanceFactoryMock();
return {
alertInstanceFactory: jest
.fn<jest.Mocked<AlertInstance>, []>()
.mockReturnValue(alertInstanceFactoryMock),
callCluster: jest.fn(),
savedObjectsClient: savedObjectsClientMock.create(),
search: createScopedSeachApiMock().search,
};
};

export type AlertServicesMock = ReturnType<typeof createAlertServicesMock>;

export const alertsMock = {
createAlertInstanceFactory: createAlertInstanceFactoryMock,
createSetup: createSetupMock,
createStart: createStartMock,
createAlertServices: createAlertServicesMock,
};

0 comments on commit d2265d9

Please sign in to comment.