Skip to content

Commit

Permalink
Refactoring network HTTP to use useSearchStrategy (#136115)
Browse files Browse the repository at this point in the history
* Refactoring network HTTP to use useSearchStrategy

* fix unit tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
angorayc and kibanamachine authored Jul 18, 2022
1 parent 20edc9b commit b552e42
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,75 @@

import { act, renderHook } from '@testing-library/react-hooks';
import { TestProviders } from '../../../common/mock';
import { ID, useNetworkHttp } from '.';
import { NetworkType } from '../../store/model';
import { useNetworkHttp, ID } from '.';
import { useSearchStrategy } from '../../../common/containers/use_search_strategy';
import { networkModel } from '../../store';

jest.mock('../../../common/containers/use_search_strategy', () => ({
useSearchStrategy: jest.fn(),
}));
const mockUseSearchStrategy = useSearchStrategy as jest.Mock;
const mockSearch = jest.fn();

const props = {
endDate: '2020-07-08T08:20:18.966Z',
indexNames: ['auditbeat-*'],
skip: false,
startDate: '2020-07-07T08:20:18.966Z',
type: networkModel.NetworkType.page,
id: ID,
};

describe('useNetworkHttp', () => {
beforeEach(() => {
jest.clearAllMocks();
mockUseSearchStrategy.mockReturnValue({
loading: false,
result: {
edges: [],
totalCount: -1,
pageInfo: {
activePage: 0,
fakeTotalCount: 0,
showMorePagesIndicator: false,
},
},
search: mockSearch,
refetch: jest.fn(),
inspect: {},
});
});

it('runs search', () => {
renderHook(() => useNetworkHttp(props), {
wrapper: TestProviders,
});

expect(mockSearch).toHaveBeenCalled();
});

it('does not run search when skip = true', () => {
const localProps = {
...props,
skip: true,
};
renderHook(() => useNetworkHttp(localProps), {
wrapper: TestProviders,
});

expect(mockSearch).not.toHaveBeenCalled();
});

it('skip = true will cancel any running request', () => {
const abortSpy = jest.spyOn(AbortController.prototype, 'abort');
const localProps = {
docValueFields: [],
startDate: '2020-07-07T08:20:18.966Z',
endDate: '2020-07-08T08:20:18.966Z',
id: `${ID}-${NetworkType.page}`,
indexNames: ['cool'],
type: NetworkType.page,
skip: false,
...props,
};
const { rerender } = renderHook(() => useNetworkHttp(localProps), {
wrapper: TestProviders,
});
localProps.skip = true;
act(() => rerender());
expect(abortSpy).toHaveBeenCalledTimes(4);
expect(mockUseSearchStrategy).toHaveBeenCalledTimes(3);
expect(mockUseSearchStrategy.mock.calls[2][0].abort).toEqual(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@
* 2.0.
*/

import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useState, useEffect, useCallback, useMemo } from 'react';
import deepEqual from 'fast-deep-equal';
import { Subscription } from 'rxjs';

import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common';
import type { ESTermQuery } from '../../../../common/typed_json';
import type { inputsModel } from '../../../common/store';
import { useDeepEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
import type { networkModel } from '../../store';
Expand All @@ -23,21 +19,20 @@ import type {
NetworkHttpEdges,
PageInfoPaginated,
NetworkHttpRequestOptions,
NetworkHttpStrategyResponse,
SortField,
} from '../../../../common/search_strategy';
import { NetworkQueries } from '../../../../common/search_strategy';
import * as i18n from './translations';
import type { InspectResponse } from '../../../types';
import { getInspectResponse } from '../../../helpers';
import { useAppToasts } from '../../../common/hooks/use_app_toasts';

import { useSearchStrategy } from '../../../common/containers/use_search_strategy';

export const ID = 'networkHttpQuery';

export interface NetworkHttpArgs {
id: string;
ip?: string;
inspect: InspectResponse;
ip?: string;
isInspected: boolean;
loadPage: (newActivePage: number) => void;
networkHttp: NetworkHttpEdges[];
Expand All @@ -47,14 +42,14 @@ export interface NetworkHttpArgs {
}

interface UseNetworkHttp {
endDate: string;
filterQuery?: ESTermQuery | string;
id: string;
ip?: string;
indexNames: string[];
type: networkModel.NetworkType;
filterQuery?: ESTermQuery | string;
endDate: string;
startDate: string;
ip?: string;
skip: boolean;
startDate: string;
type: networkModel.NetworkType;
}

export const useNetworkHttp = ({
Expand All @@ -69,11 +64,6 @@ export const useNetworkHttp = ({
}: UseNetworkHttp): [boolean, NetworkHttpArgs] => {
const getHttpSelector = useMemo(() => networkSelectors.httpSelector(), []);
const { activePage, limit, sort } = useDeepEqualSelector((state) => getHttpSelector(state, type));
const { data } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop);
const abortCtrl = useRef(new AbortController());
const searchSubscription$ = useRef(new Subscription());
const [loading, setLoading] = useState(false);

const [networkHttpRequest, setHostRequest] = useState<NetworkHttpRequestOptions | null>(null);

Expand All @@ -93,72 +83,51 @@ export const useNetworkHttp = ({
[limit]
);

const [networkHttpResponse, setNetworkHttpResponse] = useState<NetworkHttpArgs>({
networkHttp: [],
id,
inspect: {
dsl: [],
response: [],
const {
loading,
result: response,
search,
refetch,
inspect,
} = useSearchStrategy<NetworkQueries.http>({
factoryQueryType: NetworkQueries.http,
initialResult: {
edges: [],
totalCount: -1,
pageInfo: {
activePage: 0,
fakeTotalCount: 0,
showMorePagesIndicator: false,
},
},
isInspected: false,
loadPage: wrappedLoadMore,
pageInfo: {
activePage: 0,
fakeTotalCount: 0,
showMorePagesIndicator: false,
},
refetch: refetch.current,
totalCount: -1,
errorMessage: i18n.FAIL_NETWORK_HTTP,
abort: skip,
});
const { addError, addWarning } = useAppToasts();

const networkHttpSearch = useCallback(
(request: NetworkHttpRequestOptions | null) => {
if (request == null || skip) {
return;
}
const asyncSearch = async () => {
abortCtrl.current = new AbortController();
setLoading(true);
searchSubscription$.current = data.search
.search<NetworkHttpRequestOptions, NetworkHttpStrategyResponse>(request, {
strategy: 'securitySolutionSearchStrategy',
abortSignal: abortCtrl.current.signal,
})
.subscribe({
next: (response) => {
if (isCompleteResponse(response)) {
setLoading(false);
setNetworkHttpResponse((prevResponse) => ({
...prevResponse,
networkHttp: response.edges,
inspect: getInspectResponse(response, prevResponse.inspect),
pageInfo: response.pageInfo,
refetch: refetch.current,
totalCount: response.totalCount,
}));
searchSubscription$.current.unsubscribe();
} else if (isErrorResponse(response)) {
setLoading(false);
addWarning(i18n.ERROR_NETWORK_HTTP);
searchSubscription$.current.unsubscribe();
}
},
error: (msg) => {
setLoading(false);
addError(msg, {
title: i18n.FAIL_NETWORK_HTTP,
});
searchSubscription$.current.unsubscribe();
},
});
};
searchSubscription$.current.unsubscribe();
abortCtrl.current.abort();
asyncSearch();
refetch.current = asyncSearch;
},
[data.search, addError, addWarning, skip]
const networkHttpResponse = useMemo(
() => ({
endDate,
networkHttp: response.edges,
id,
inspect,
isInspected: false,
loadPage: wrappedLoadMore,
pageInfo: response.pageInfo,
refetch,
startDate,
totalCount: response.totalCount,
}),
[
endDate,
id,
inspect,
refetch,
response.edges,
response.pageInfo,
response.totalCount,
startDate,
wrappedLoadMore,
]
);

useEffect(() => {
Expand All @@ -185,20 +154,10 @@ export const useNetworkHttp = ({
}, [activePage, indexNames, endDate, filterQuery, ip, limit, startDate, sort]);

useEffect(() => {
networkHttpSearch(networkHttpRequest);
return () => {
searchSubscription$.current.unsubscribe();
abortCtrl.current.abort();
};
}, [networkHttpRequest, networkHttpSearch]);

useEffect(() => {
if (skip) {
setLoading(false);
searchSubscription$.current.unsubscribe();
abortCtrl.current.abort();
if (!skip && networkHttpRequest) {
search(networkHttpRequest);
}
}, [skip]);
}, [networkHttpRequest, search, skip]);

return [loading, networkHttpResponse];
};

0 comments on commit b552e42

Please sign in to comment.