From 5fd5b272a139a6c271455ebc0a9ad7b2f90d3182 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Tue, 19 Jul 2022 20:12:23 +0100 Subject: [PATCH] Refactoring network TLS to use useSearchStrategy (#136187) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../network/containers/tls/index.test.tsx | 73 +++++++-- .../public/network/containers/tls/index.tsx | 144 ++++++------------ 2 files changed, 111 insertions(+), 106 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/containers/tls/index.test.tsx b/x-pack/plugins/security_solution/public/network/containers/tls/index.test.tsx index f6899475b4647..db1c028b74fb3 100644 --- a/x-pack/plugins/security_solution/public/network/containers/tls/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/tls/index.test.tsx @@ -8,28 +8,77 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { TestProviders } from '../../../common/mock'; import { ID, useNetworkTls } from '.'; -import { NetworkType } from '../../store/model'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; +import { networkModel } from '../../store'; import { FlowTargetSourceDest } from '../../../../common/search_strategy'; +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', + flowTarget: FlowTargetSourceDest.source, + id: ID, + indexNames: ['auditbeat-*'], + ip: '139.177.197.217', + skip: false, + startDate: '2020-07-07T08:20:18.966Z', + type: networkModel.NetworkType.page, +}; + describe('useNetworkTls', () => { + 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(() => useNetworkTls(props), { + wrapper: TestProviders, + }); + + expect(mockSearch).toHaveBeenCalled(); + }); + + it('does not run search when skip = true', () => { + const localProps = { + ...props, + skip: true, + }; + renderHook(() => useNetworkTls(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: [], - flowTarget: FlowTargetSourceDest.source, - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - id: `${ID}-${NetworkType.page}`, - indexNames: ['cool'], - ip: '1.1.1.1', - type: NetworkType.page, - skip: false, + ...props, }; const { rerender } = renderHook(() => useNetworkTls(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); }); }); diff --git a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx index 1609b76612b76..9d13900619a08 100644 --- a/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/tls/index.tsx @@ -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'; @@ -26,9 +22,8 @@ import type { import { NetworkQueries } from '../../../../common/search_strategy/security_solution/network'; import * as i18n from './translations'; -import { getInspectResponse } from '../../../helpers'; import type { FlowTargetSourceDest, PageInfoPaginated } from '../../../../common/search_strategy'; -import { useAppToasts } from '../../../common/hooks/use_app_toasts'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; export const ID = 'networkTlsQuery'; @@ -70,17 +65,12 @@ export const useNetworkTls = ({ const { activePage, limit, sort } = useDeepEqualSelector((state) => getTlsSelector(state, type, flowTarget) ); - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkTlsRequest, setHostRequest] = useState(null); + const [networkTlsRequest, setNetworkTlsRequest] = useState(null); const wrappedLoadMore = useCallback( (newActivePage: number) => { - setHostRequest((prevRequest) => { + setNetworkTlsRequest((prevRequest) => { if (!prevRequest) { return prevRequest; } @@ -94,79 +84,55 @@ export const useNetworkTls = ({ [limit] ); - const [networkTlsResponse, setNetworkTlsResponse] = useState({ - tls: [], - id: ID, - inspect: { - dsl: [], - response: [], + const { + loading, + result: response, + search, + refetch, + inspect, + } = useSearchStrategy({ + factoryQueryType: NetworkQueries.tls, + 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_TLS, + abort: skip, }); - const { addError, addWarning } = useAppToasts(); - - const networkTlsSearch = useCallback( - (request: NetworkTlsRequestOptions | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (isCompleteResponse(response)) { - setLoading(false); - setNetworkTlsResponse((prevResponse) => ({ - ...prevResponse, - tls: 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_TLS); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_TLS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, addWarning, skip] + const networkTlsResponse = useMemo( + () => ({ + endDate, + tls: 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(() => { - setHostRequest((prevRequest) => { + setNetworkTlsRequest((prevRequest) => { const myRequest = { ...(prevRequest ?? {}), defaultIndex: indexNames, @@ -190,20 +156,10 @@ export const useNetworkTls = ({ }, [activePage, indexNames, endDate, filterQuery, limit, startDate, sort, flowTarget, ip, id]); useEffect(() => { - networkTlsSearch(networkTlsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkTlsRequest, networkTlsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); + if (!skip && networkTlsRequest) { + search(networkTlsRequest); } - }, [skip]); + }, [networkTlsRequest, search, skip]); return [loading, networkTlsResponse]; };