Skip to content

Commit

Permalink
[8.x] [Security solution] Knowledge base unit tests (#200207) (#200651)
Browse files Browse the repository at this point in the history
# Backport

This will backport the following commits from `main` to `8.x`:
- [[Security solution] Knowledge base unit tests
(#200207)](#200207)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Steph
Milovic","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-11-18T20:13:58Z","message":"[Security
solution] Knowledge base unit tests
(#200207)","sha":"d57e3b0ea0a1b47975f317f48c6a4907702edf3e","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:
SecuritySolution","Team:Security Generative
AI","backport:version","v8.17.0"],"number":200207,"url":"https://github.com/elastic/kibana/pull/200207","mergeCommit":{"message":"[Security
solution] Knowledge base unit tests
(#200207)","sha":"d57e3b0ea0a1b47975f317f48c6a4907702edf3e"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/200207","number":200207,"mergeCommit":{"message":"[Security
solution] Knowledge base unit tests
(#200207)","sha":"d57e3b0ea0a1b47975f317f48c6a4907702edf3e"}},{"branch":"8.x","label":"v8.17.0","labelRegex":"^v8.17.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
  • Loading branch information
stephmilovic authored Nov 18, 2024
1 parent 29e3669 commit 25f42b7
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 25f42b7

Please sign in to comment.