Skip to content

Commit

Permalink
add more unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Li <joshuali925@gmail.com>
  • Loading branch information
joshuali925 committed Dec 23, 2023
1 parent 070620d commit b343245
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,84 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { genericReducer } from '../hooks';
import { renderHook } from '@testing-library/react-hooks';
import { SavedObjectsFindResponsePublic } from '../../../../../../../../src/core/public';
import { coreMock } from '../../../../../../../../src/core/public/mocks';
import * as coreServices from '../../../../../../common/utils/core_services';
import { coreRefs } from '../../../../../framework/core_refs';
import { genericReducer, useCatIndices, useGetIndexPatterns } from '../hooks';

const coreStartMock = coreMock.createStart();

describe('useCatIndices', () => {
const httpMock = coreStartMock.http;

beforeEach(() => {
jest.spyOn(coreServices, 'getOSDHttp').mockReturnValue(httpMock);
});

afterEach(() => {
jest.clearAllMocks();
});

it('should return indices', async () => {
httpMock.get.mockResolvedValueOnce([{ index: 'test1' }, { index: 'test2' }]);

const { result, waitForNextUpdate } = renderHook(() => useCatIndices());
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual([{ label: 'test1' }, { label: 'test2' }]);
});

it('should handle errors', async () => {
httpMock.get.mockRejectedValueOnce('API failed');

const { result, waitForNextUpdate } = renderHook(() => useCatIndices());
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toBe(undefined);
expect(result.current.error).toEqual('API failed');
});
});

describe('useGetIndexPatterns', () => {
const savedObjectsClientMock = coreStartMock.savedObjects.client as jest.Mocked<
typeof coreStartMock.savedObjects.client
>;

beforeAll(() => {
coreRefs.savedObjectsClient = savedObjectsClientMock;
});

afterEach(() => {
jest.clearAllMocks();
});

it('should return index patterns', async () => {
savedObjectsClientMock.find.mockResolvedValueOnce({
savedObjects: [{ attributes: { title: 'test1' } }, { attributes: { title: 'test2' } }],
} as SavedObjectsFindResponsePublic);

const { result, waitForNextUpdate } = renderHook(() => useGetIndexPatterns());
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual([{ label: 'test1' }, { label: 'test2' }]);
});

it('should handle errors', async () => {
savedObjectsClientMock.find.mockRejectedValueOnce('API failed');

const { result, waitForNextUpdate } = renderHook(() => useGetIndexPatterns());
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toBe(undefined);
expect(result.current.error).toEqual('API failed');
});
});

describe('genericReducer', () => {
it('should return original state', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { configureStore } from '@reduxjs/toolkit';
import { fireEvent, render, waitFor } from '@testing-library/react';
import React, { ComponentProps } from 'react';
import { Provider } from 'react-redux';
import { coreMock } from '../../../../../../../../src/core/public/mocks';
import { QUERY_ASSIST_API } from '../../../../../../common/constants/query_assist';
import * as coreServices from '../../../../../../common/utils/core_services';
import { coreRefs } from '../../../../../framework/core_refs';
import { rootReducer } from '../../../../../framework/redux/reducers';
import { initialTabId } from '../../../../../framework/redux/store/shared_state';
import { QueryAssistInput } from '../input';

const renderQueryAssistInput = (
overrideProps: Partial<ComponentProps<typeof QueryAssistInput>> = {}
) => {
const preloadedState = {};
const store = configureStore({ reducer: rootReducer, preloadedState });
const props: ComponentProps<typeof QueryAssistInput> = Object.assign(
{
handleQueryChange: jest.fn(),
handleTimeRangePickerRefresh: jest.fn(),
tabId: initialTabId,
setNeedsUpdate: jest.fn(),
selectedIndex: [{ label: 'selected-test-index' }],
nlqInput: 'test-input',
setNlqInput: jest.fn(),
},
overrideProps
);
const component = render(
<Provider store={store}>
<QueryAssistInput {...props} />
</Provider>
);
return { component, props, store };
};

describe('<QueryAssistInput /> spec', () => {
const coreStartMock = coreMock.createStart();
coreRefs.toasts = coreStartMock.notifications.toasts;
const httpMock = coreStartMock.http;

beforeEach(() => {
jest.spyOn(coreServices, 'getOSDHttp').mockReturnValue(httpMock);
});

afterEach(() => {
jest.clearAllMocks();
});

it('should call generate ppl based on nlq input value', async () => {
httpMock.post.mockResolvedValueOnce('source = index');

const { component, props } = renderQueryAssistInput();

await waitFor(() => {
fireEvent.click(component.getByTestId('query-assist-generate-and-run-button'));
});

expect(httpMock.post).toBeCalledWith(QUERY_ASSIST_API.GENERATE_PPL, {
body: '{"question":"test-input","index":"selected-test-index"}',
});
expect(props.handleQueryChange).toBeCalledWith('source = index');
});

it('should display toast for generate errors', async () => {
httpMock.post.mockRejectedValueOnce({ body: { statusCode: 429 } });

const { component } = renderQueryAssistInput();
await waitFor(() => {
fireEvent.click(component.getByTestId('query-assist-generate-button'));
});

expect(coreRefs.toasts!.addError).toBeCalledWith(
{
message: 'Request is throttled. Try again later or contact your administrator',
statusCode: 429,
},
{ title: 'Failed to generate results' }
);
});

it('should call summarize for generate and run errors', async () => {
httpMock.post.mockRejectedValueOnce({ body: { statusCode: 429 } }).mockResolvedValueOnce({
summary: 'too many requests',
suggestedQuestions: ['1', '2'],
});

const { component } = renderQueryAssistInput();
await waitFor(() => {
fireEvent.click(component.getByTestId('query-assist-generate-and-run-button'));
});

expect(httpMock.post).toBeCalledWith(QUERY_ASSIST_API.GENERATE_PPL, {
body: '{"question":"test-input","index":"selected-test-index"}',
});
expect(httpMock.post).toBeCalledWith(QUERY_ASSIST_API.SUMMARIZE, {
body:
'{"question":"test-input","index":"selected-test-index","isError":true,"query":"","response":"{\\"statusCode\\":429}"}',
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export const QueryAssistInput: React.FC<Props> = (props) => {
isDisabled={generating || generatingOrRunning}
iconSide="right"
fill={false}
data-test-subj="query-assist-generate-button"
style={{ width: 160 }}
>
Generate query
Expand All @@ -350,6 +351,7 @@ export const QueryAssistInput: React.FC<Props> = (props) => {
iconSide="right"
type="submit"
fill={barSelected}
data-test-subj="query-assist-generate-and-run-button"
style={{ width: 175 }}
>
Generate and run
Expand Down

0 comments on commit b343245

Please sign in to comment.