Skip to content

Commit

Permalink
[Security solution] Knowledge base unit tests (elastic#200207)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic authored Nov 18, 2024
1 parent a8fd0c9 commit d57e3b0
Show file tree
Hide file tree
Showing 37 changed files with 2,290 additions and 138 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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 {
useCreateKnowledgeBaseEntry,
UseCreateKnowledgeBaseEntryParams,
} from './use_create_knowledge_base_entry';
import { useInvalidateKnowledgeBaseEntries } from './use_knowledge_base_entries';

jest.mock('./use_knowledge_base_entries', () => ({
useInvalidateKnowledgeBaseEntries: jest.fn(),
}));

jest.mock('@tanstack/react-query', () => ({
useMutation: jest.fn().mockImplementation((queryKey, fn, opts) => {
return {
mutate: async (variables: unknown) => {
try {
const res = await fn(variables);
opts.onSuccess(res);
opts.onSettled();
return Promise.resolve(res);
} catch (e) {
opts.onError(e);
opts.onSettled();
}
},
};
}),
}));

const http = {
post: jest.fn(),
};
const toasts = {
addError: jest.fn(),
addSuccess: jest.fn(),
};
const defaultProps = { http, toasts } as unknown as UseCreateKnowledgeBaseEntryParams;
const defaultArgs = { title: 'Test Entry' };
describe('useCreateKnowledgeBaseEntry', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should call the mutation function on success', async () => {
const invalidateKnowledgeBaseEntries = jest.fn();
(useInvalidateKnowledgeBaseEntries as jest.Mock).mockReturnValue(
invalidateKnowledgeBaseEntries
);
http.post.mockResolvedValue({});

const { result } = renderHook(() => useCreateKnowledgeBaseEntry(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(http.post).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
body: JSON.stringify(defaultArgs),
})
);
expect(toasts.addSuccess).toHaveBeenCalledWith({
title: expect.any(String),
});
expect(invalidateKnowledgeBaseEntries).toHaveBeenCalled();
});

it('should call the onError function on error', async () => {
const error = new Error('Test Error');
http.post.mockRejectedValue(error);

const { result } = renderHook(() => useCreateKnowledgeBaseEntry(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(toasts.addError).toHaveBeenCalledWith(error, {
title: expect.any(String),
});
});

it('should call the onSettled function after mutation', async () => {
const invalidateKnowledgeBaseEntries = jest.fn();
(useInvalidateKnowledgeBaseEntries as jest.Mock).mockReturnValue(
invalidateKnowledgeBaseEntries
);
http.post.mockResolvedValue({});

const { result } = renderHook(() => useCreateKnowledgeBaseEntry(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(invalidateKnowledgeBaseEntries).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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 {
useDeleteKnowledgeBaseEntries,
UseDeleteKnowledgeEntriesParams,
} from './use_delete_knowledge_base_entries';
import { useInvalidateKnowledgeBaseEntries } from './use_knowledge_base_entries';

jest.mock('./use_knowledge_base_entries', () => ({
useInvalidateKnowledgeBaseEntries: jest.fn(),
}));

jest.mock('@tanstack/react-query', () => ({
useMutation: jest.fn().mockImplementation((queryKey, fn, opts) => {
return {
mutate: async (variables: unknown) => {
try {
const res = await fn(variables);
opts.onSuccess(res);
opts.onSettled();
return Promise.resolve(res);
} catch (e) {
opts.onError(e);
opts.onSettled();
}
},
};
}),
}));

const http = {
post: jest.fn(),
};
const toasts = {
addError: jest.fn(),
};
const defaultProps = { http, toasts } as unknown as UseDeleteKnowledgeEntriesParams;
const defaultArgs = { ids: ['1'], query: '' };

describe('useDeleteKnowledgeBaseEntries', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should call the mutation function on success', async () => {
const invalidateKnowledgeBaseEntries = jest.fn();
(useInvalidateKnowledgeBaseEntries as jest.Mock).mockReturnValue(
invalidateKnowledgeBaseEntries
);
http.post.mockResolvedValue({});

const { result } = renderHook(() => useDeleteKnowledgeBaseEntries(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(http.post).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
body: JSON.stringify({ delete: { query: '', ids: ['1'] } }),
version: '1',
})
);
expect(invalidateKnowledgeBaseEntries).toHaveBeenCalled();
});

it('should call the onError function on error', async () => {
const error = new Error('Test Error');
http.post.mockRejectedValue(error);

const { result } = renderHook(() => useDeleteKnowledgeBaseEntries(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(toasts.addError).toHaveBeenCalledWith(error, {
title: expect.any(String),
});
});

it('should call the onSettled function after mutation', async () => {
const invalidateKnowledgeBaseEntries = jest.fn();
(useInvalidateKnowledgeBaseEntries as jest.Mock).mockReturnValue(
invalidateKnowledgeBaseEntries
);
http.post.mockResolvedValue({});

const { result } = renderHook(() => useDeleteKnowledgeBaseEntries(defaultProps));

await act(async () => {
// @ts-ignore
await result.current.mutate(defaultArgs);
});

expect(invalidateKnowledgeBaseEntries).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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 { renderHook } from '@testing-library/react-hooks';
import { useKnowledgeBaseEntries } from './use_knowledge_base_entries';
import { HttpSetup } from '@kbn/core/public';
import { IToasts } from '@kbn/core-notifications-browser';
import { TestProviders } from '../../../../mock/test_providers/test_providers';

describe('useKnowledgeBaseEntries', () => {
const httpMock: HttpSetup = {
fetch: jest.fn(),
} as unknown as HttpSetup;
const toastsMock: IToasts = {
addError: jest.fn(),
} as unknown as IToasts;

it('fetches knowledge base entries successfully', async () => {
(httpMock.fetch as jest.Mock).mockResolvedValue({
page: 1,
perPage: 100,
total: 1,
data: [{ id: '1', title: 'Entry 1' }],
});

const { result, waitForNextUpdate } = renderHook(
() => useKnowledgeBaseEntries({ http: httpMock, enabled: true }),
{
wrapper: TestProviders,
}
);
expect(result.current.fetchStatus).toEqual('fetching');

await waitForNextUpdate();

expect(result.current.data).toEqual({
page: 1,
perPage: 100,
total: 1,
data: [{ id: '1', title: 'Entry 1' }],
});
});

it('handles fetch error', async () => {
const error = new Error('Fetch error');
(httpMock.fetch as jest.Mock).mockRejectedValue(error);

const { waitForNextUpdate } = renderHook(
() => useKnowledgeBaseEntries({ http: httpMock, toasts: toastsMock, enabled: true }),
{
wrapper: TestProviders,
}
);

await waitForNextUpdate();

expect(toastsMock.addError).toHaveBeenCalledWith(error, {
title: 'Error fetching Knowledge Base entries',
});
});

it('does not fetch when disabled', async () => {
const { result } = renderHook(
() => useKnowledgeBaseEntries({ http: httpMock, enabled: false }),
{
wrapper: TestProviders,
}
);

expect(result.current.fetchStatus).toEqual('idle');
});
});
Loading

0 comments on commit d57e3b0

Please sign in to comment.