[Security Solution][Endpoint] Unit Test cases to cover CaseView action/comment refresh and Endpoint isolation api (#103560)

* Tests for `<CaseView>` `refreshRef` prop
* Tests for Isolation API update of cases
This commit is contained in:
Paul Tavares 2021-06-30 10:51:36 -04:00 committed by GitHub
parent 2f457da640
commit 1b1e29c756
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 136 additions and 7 deletions

View file

@ -9,7 +9,7 @@ import React from 'react';
import { mount } from 'enzyme';
import '../../common/mock/match_media';
import { CaseComponent, CaseComponentProps, CaseView } from '.';
import { CaseComponent, CaseComponentProps, CaseView, CaseViewProps } from '.';
import {
basicCase,
basicCaseClosed,
@ -789,6 +789,69 @@ describe('CaseView ', () => {
});
});
describe('when a `refreshRef` prop is provided', () => {
let refreshRef: CaseViewProps['refreshRef'];
beforeEach(() => {
(useGetCase as jest.Mock).mockImplementation(() => defaultGetCase);
refreshRef = React.createRef();
mount(
<TestProviders>
<CaseView
{...{
refreshRef,
allCasesNavigation: {
href: 'all-cases-href',
onClick: jest.fn(),
},
caseDetailsNavigation: {
href: 'case-details-href',
onClick: jest.fn(),
},
caseId: '1234',
configureCasesNavigation: {
href: 'configure-cases-href',
onClick: jest.fn(),
},
getCaseDetailHrefWithCommentId: jest.fn(),
onComponentInitialized: jest.fn(),
ruleDetailsNavigation: {
href: jest.fn(),
onClick: jest.fn(),
},
showAlertDetails: jest.fn(),
useFetchAlertData: jest.fn().mockReturnValue([false, alertsHit[0]]),
userCanCrud: true,
}}
/>
</TestProviders>
);
});
it('should set it with expected refresh interface', async () => {
expect(refreshRef!.current).toEqual({
refreshUserActionsAndComments: expect.any(Function),
refreshCase: expect.any(Function),
});
});
it('should refresh actions and comments', async () => {
await waitFor(() => {
refreshRef!.current!.refreshUserActionsAndComments();
expect(fetchCaseUserActions).toBeCalledWith('1234', 'resilient-2', undefined);
expect(fetchCase).toBeCalledWith(true);
});
});
it('should refresh case', async () => {
await waitFor(() => {
refreshRef!.current!.refreshCase();
expect(fetchCase).toBeCalledWith(); // No args given to `fetchCase()`
});
});
});
describe('Callouts', () => {
it('it shows the danger callout when a connector has been deleted', async () => {
useConnectorsMock.mockImplementation(() => ({ connectors: [], loading: false }));

View file

@ -10,7 +10,6 @@ export { CasesClient } from './client';
import { ConfigType, ConfigSchema } from './config';
import { CasePlugin } from './plugin';
export { CaseRequestContext } from './types';
export const config: PluginConfigDescriptor<ConfigType> = {
schema: ConfigSchema,
deprecations: ({ renameFromRoot }) => [

View file

@ -31,6 +31,12 @@ import { MetadataRequestContext } from './routes/metadata/handlers';
import { LicenseService } from '../../common/license';
import { SecuritySolutionRequestHandlerContext } from '../types';
import { parseExperimentalConfigValue } from '../../common/experimental_features';
// A TS error (TS2403) is thrown when attempting to export the mock function below from Cases
// plugin server `index.ts`. Its unclear what is actually causing the error. Since this is a Mock
// file and not bundled with the application, adding a eslint disable below and using import from
// a restricted path.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { createCasesClientMock } from '../../../cases/server/client/mocks';
/**
* Creates a mocked EndpointAppContext.
@ -69,7 +75,10 @@ export const createMockEndpointAppContextService = (
export const createMockEndpointAppContextServiceStartContract = (): jest.Mocked<EndpointAppContextServiceStartContract> => {
const factory = new AppClientFactory();
const config = createMockConfig();
const casesClientMock = createCasesClientMock();
factory.setup({ getSpaceId: () => 'mockSpace', config });
return {
agentService: createMockAgentService(),
packageService: createMockPackageService(),
@ -88,7 +97,7 @@ export const createMockEndpointAppContextServiceStartContract = (): jest.Mocked<
exceptionListsClient: listMock.getExceptionListClient(),
packagePolicyService: createPackagePolicyServiceMock(),
cases: {
getCasesClientWithRequest: jest.fn(),
getCasesClientWithRequest: jest.fn(async () => casesClientMock),
},
};
};

View file

@ -6,7 +6,7 @@
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import { KibanaResponseFactory, RequestHandler, RouteConfig } from 'kibana/server';
import { KibanaRequest, KibanaResponseFactory, RequestHandler, RouteConfig } from 'kibana/server';
import {
elasticsearchServiceMock,
httpServerMock,
@ -37,15 +37,17 @@ import {
} from '../../../../common/endpoint/constants';
import {
EndpointAction,
HostIsolationRequestBody,
HostIsolationResponse,
HostMetadata,
} from '../../../../common/endpoint/types';
import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data';
import { createV2SearchResponse } from '../metadata/support/test_support';
import { ElasticsearchAssetType } from '../../../../../fleet/common';
import { CasesClientMock } from '../../../../../cases/server/client/mocks';
interface CallRouteInterface {
body?: any;
body?: HostIsolationRequestBody;
idxResponse?: any;
searchResponse?: HostMetadata;
mockUser?: any;
@ -358,8 +360,64 @@ describe('Host Isolation', () => {
});
describe('Cases', () => {
it.todo('logs a comment to the provided case');
it.todo('logs a comment to any cases associated with the given alert');
let casesClient: CasesClientMock;
const getCaseIdsFromAttachmentAddService = () => {
return casesClient.attachments.add.mock.calls.map(([addArgs]) => addArgs.caseId);
};
beforeEach(async () => {
casesClient = (await endpointAppContextService.getCasesClient(
{} as KibanaRequest
)) as CasesClientMock;
let counter = 1;
casesClient.cases.getCasesByAlertID.mockImplementation(async () => {
return [
{
id: `case-${counter++}`,
title: 'case',
},
];
});
});
it('logs a comment to the provided cases', async () => {
await callRoute(ISOLATE_HOST_ROUTE, {
body: { endpoint_ids: ['XYZ'], case_ids: ['one', 'two'] },
});
expect(casesClient.attachments.add).toHaveBeenCalledTimes(2);
expect(getCaseIdsFromAttachmentAddService()).toEqual(
expect.arrayContaining(['one', 'two'])
);
});
it('logs a comment to any cases associated with the given alerts', async () => {
await callRoute(ISOLATE_HOST_ROUTE, {
body: { endpoint_ids: ['XYZ'], alert_ids: ['one', 'two'] },
});
expect(getCaseIdsFromAttachmentAddService()).toEqual(
expect.arrayContaining(['case-1', 'case-2'])
);
});
it('logs a comment to any cases provided on input along with cases associated with the given alerts', async () => {
await callRoute(ISOLATE_HOST_ROUTE, {
// 'case-1` provided on `case_ids` should be dedupped
body: {
endpoint_ids: ['XYZ'],
case_ids: ['ONE', 'TWO', 'case-1'],
alert_ids: ['one', 'two'],
},
});
expect(casesClient.attachments.add).toHaveBeenCalledTimes(4);
expect(getCaseIdsFromAttachmentAddService()).toEqual(
expect.arrayContaining(['ONE', 'TWO', 'case-1', 'case-2'])
);
});
});
});
});