Skip to content

Commit

Permalink
Added api tests for deleteFileAttachments.
Browse files Browse the repository at this point in the history
Added FileDeleteButtonIcon tests.
Added useDeleteFileAttachment tests.
  • Loading branch information
adcoelho committed Apr 5, 2023
1 parent f5167f1 commit a815917
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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 React from 'react';

import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import type { AppMockRenderer } from '../../common/mock';

import { createAppMockRenderer } from '../../common/mock';
import { basicCaseId, basicFileMock } from '../../containers/mock';
import { useDeleteFileAttachment } from '../../containers/use_delete_file_attachment';
import { FileDeleteButtonIcon } from './file_delete_button_icon';

jest.mock('../../containers/use_delete_file_attachment');

const useDeleteFileAttachmentMock = useDeleteFileAttachment as jest.Mock;

describe('FileDeleteButtonIcon', () => {
let appMockRender: AppMockRenderer;
const mutate = jest.fn();

useDeleteFileAttachmentMock.mockReturnValue({ isLoading: false, mutate });

beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});

it('renders delete button correctly', async () => {
appMockRender.render(<FileDeleteButtonIcon caseId={basicCaseId} fileId={basicFileMock.id} />);

expect(await screen.findByTestId('cases-files-delete-button')).toBeInTheDocument();

expect(useDeleteFileAttachmentMock).toBeCalledTimes(1);
});

it('clicking delete button calls deleteFileAttachment with proper params', async () => {
appMockRender.render(<FileDeleteButtonIcon caseId={basicCaseId} fileId={basicFileMock.id} />);

const deleteButton = await screen.findByTestId('cases-files-delete-button');

expect(deleteButton).toBeInTheDocument();

userEvent.click(deleteButton);

await waitFor(() => {
expect(mutate).toHaveBeenCalledTimes(1);
expect(mutate).toHaveBeenCalledWith({
caseId: basicCaseId,
fileId: basicFileMock.id,
successToasterTitle: 'File deleted successfully',
});
});
});
});
10 changes: 10 additions & 0 deletions x-pack/plugins/cases/public/containers/__mocks__/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,13 @@ export const getCaseConnectors = async (

export const getCaseUsers = async (caseId: string, signal: AbortSignal): Promise<CaseUsers> =>
Promise.resolve(getCaseUsersMockResponse());

export const deleteFileAttachments = async ({
caseId,
fileIds,
signal,
}: {
caseId: string;
fileIds: string[];
signal: AbortSignal;
}): Promise<void> => Promise.resolve(undefined);
27 changes: 27 additions & 0 deletions x-pack/plugins/cases/public/containers/api.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
INTERNAL_BULK_CREATE_ATTACHMENTS_URL,
SECURITY_SOLUTION_OWNER,
INTERNAL_GET_CASE_USER_ACTIONS_STATS_URL,
INTERNAL_DELETE_FILE_ATTACHMENTS_URL,
} from '../../common/constants';

import {
Expand All @@ -37,6 +38,7 @@ import {
postComment,
getCaseConnectors,
getCaseUserActionsStats,
deleteFileAttachments,
} from './api';

import {
Expand All @@ -59,6 +61,7 @@ import {
caseUserActionsWithRegisteredAttachmentsSnake,
basicPushSnake,
getCaseUserActionsStatsResponse,
basicFileMock,
} from './mock';

import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './use_get_cases';
Expand Down Expand Up @@ -820,6 +823,30 @@ describe('Cases API', () => {
});
});

describe('deleteFileAttachments', () => {
beforeEach(() => {
fetchMock.mockClear();
fetchMock.mockResolvedValue(null);
});

it('should be called with correct url, method, signal and body', async () => {
const resp = await deleteFileAttachments({
caseId: basicCaseId,
fileIds: [basicFileMock.id],
signal: abortCtrl.signal,
});
expect(fetchMock).toHaveBeenCalledWith(
INTERNAL_DELETE_FILE_ATTACHMENTS_URL.replace('{case_id}', basicCaseId),
{
method: 'POST',
body: JSON.stringify({ ids: [basicFileMock.id] }),
signal: abortCtrl.signal,
}
);
expect(resp).toBe(undefined);
});
});

describe('pushCase', () => {
const connectorId = 'connectorId';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* 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 { act, renderHook } from '@testing-library/react-hooks';
import * as api from './api';
import { basicCaseId, basicFileMock } from './mock';
import { useRefreshCaseViewPage } from '../components/case_view/use_on_refresh_case_view_page';
import { useToasts } from '../common/lib/kibana';
import type { AppMockRenderer } from '../common/mock';
import { createAppMockRenderer } from '../common/mock';
import { useDeleteFileAttachment } from './use_delete_file_attachment';

jest.mock('./api');
jest.mock('../common/lib/kibana');
jest.mock('../components/case_view/use_on_refresh_case_view_page');

const successToasterTitle = 'Deleted';

describe('useDeleteFileAttachment', () => {
const addSuccess = jest.fn();
const addError = jest.fn();

(useToasts as jest.Mock).mockReturnValue({ addSuccess, addError });

let appMockRender: AppMockRenderer;

beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});

it('init', async () => {
const { result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});

expect(result.current).toBeTruthy();
});

it('calls deleteFileAttachment with correct arguments - case', async () => {
const spyOnDeleteFileAttachments = jest.spyOn(api, 'deleteFileAttachments');

const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});

act(() => {
result.current.mutate({
caseId: basicCaseId,
fileId: basicFileMock.id,
successToasterTitle,
});
});

await waitForNextUpdate();

expect(spyOnDeleteFileAttachments).toHaveBeenCalledWith({
caseId: basicCaseId,
fileIds: [basicFileMock.id],
signal: expect.any(AbortSignal),
});
});

it('refreshes the case page view', async () => {
const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});

act(() =>
result.current.mutate({
caseId: basicCaseId,
fileId: basicFileMock.id,
successToasterTitle,
})
);

await waitForNextUpdate();

expect(useRefreshCaseViewPage()).toBeCalled();
});

it('shows a success toaster correctly', async () => {
const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});

act(() =>
result.current.mutate({
caseId: basicCaseId,
fileId: basicFileMock.id,
successToasterTitle,
})
);

await waitForNextUpdate();

expect(addSuccess).toHaveBeenCalledWith({
title: successToasterTitle,
className: 'eui-textBreakWord',
});
});

it('sets isError when fails to delete a file attachment', async () => {
const spyOnDeleteFileAttachments = jest.spyOn(api, 'deleteFileAttachments');
spyOnDeleteFileAttachments.mockRejectedValue(new Error('Error'));

const { waitForNextUpdate, result } = renderHook(() => useDeleteFileAttachment(), {
wrapper: appMockRender.AppWrapper,
});

act(() =>
result.current.mutate({
caseId: basicCaseId,
fileId: basicFileMock.id,
successToasterTitle,
})
);

await waitForNextUpdate();

expect(spyOnDeleteFileAttachments).toBeCalledWith({
caseId: basicCaseId,
fileIds: [basicFileMock.id],
signal: expect.any(AbortSignal),
});

expect(addError).toHaveBeenCalled();
expect(result.current.isError).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface MutationArgs {

export const useDeleteFileAttachment = () => {
const { showErrorToast, showSuccessToast } = useCasesToast();
const refreshCaseViewPage = useRefreshCaseViewPage();
const refreshAttachmentsTable = useRefreshCaseViewPage();

return useMutation(
({ caseId, fileId }: MutationArgs) => {
Expand All @@ -32,7 +32,7 @@ export const useDeleteFileAttachment = () => {
mutationKey: casesMutationsKeys.deleteFileAttachment,
onSuccess: (_, { successToasterTitle }) => {
showSuccessToast(successToasterTitle);
refreshCaseViewPage();
refreshAttachmentsTable();
},
onError: (error: ServerError) => {
showErrorToast(error, { title: i18n.ERROR_TITLE });
Expand Down

0 comments on commit a815917

Please sign in to comment.