From 159fe79a9e34b0fbfe1ba23f2406d63ce19f253f Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Thu, 26 May 2022 14:31:26 +0100 Subject: [PATCH] [Security Solution] New navigation panel bottom padding fix (#132951) * fix panel nav bottom padding when index does not exist * fix unrelated flacky test * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../template_wrapper/bottom_bar/index.tsx | 6 +--- .../components/query_bar/index.test.tsx | 8 ++--- .../utils/timeline/use_show_timeline.test.tsx | 29 +++++++++++++++++++ .../utils/timeline/use_show_timeline.tsx | 14 +++++++-- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx b/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx index ac669a4b331801..54ffea7edf6d69 100644 --- a/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx @@ -11,12 +11,10 @@ import React from 'react'; import { KibanaPageTemplateProps } from '@kbn/shared-ux-components'; import { AppLeaveHandler } from '@kbn/core/public'; import { useShowTimeline } from '../../../../common/utils/timeline/use_show_timeline'; -import { useSourcererDataView } from '../../../../common/containers/sourcerer'; import { TimelineId } from '../../../../../common/types/timeline'; import { AutoSaveWarningMsg } from '../../../../timelines/components/timeline/auto_save_warning'; import { Flyout } from '../../../../timelines/components/flyout'; import { useResolveRedirect } from '../../../../common/hooks/use_resolve_redirect'; -import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; export const BOTTOM_BAR_CLASSNAME = 'timeline-bottom-bar'; @@ -24,10 +22,8 @@ export const SecuritySolutionBottomBar = React.memo( ({ onAppLeave }: { onAppLeave: (handler: AppLeaveHandler) => void }) => { const [showTimeline] = useShowTimeline(); - const { indicesExist, dataViewId } = useSourcererDataView(SourcererScopeName.timeline); - useResolveRedirect(); - return (indicesExist || dataViewId === null) && showTimeline ? ( + return showTimeline ? ( <> diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx index 1620a142c15cba..0b3e9e28d31831 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx @@ -7,7 +7,7 @@ import { mount } from 'enzyme'; import React from 'react'; -import { render, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { coreMock } from '@kbn/core/public/mocks'; import { DEFAULT_FROM, DEFAULT_TO } from '../../../../common/constants'; import { TestProviders, mockIndexPattern } from '../../mock'; @@ -33,9 +33,9 @@ describe('QueryBar ', () => { // The data plugin's `SearchBar` is lazy loaded, so we need to ensure it is // available before we mount our component with Enzyme. const getWrapper = async (Component: ReturnType) => { - const { getByTestId } = render(Component); - await waitFor(() => getByTestId('queryInput')); // check for presence of query input - return mount(Component); + const wrapper = mount(Component); + await waitFor(() => wrapper.find('[data-test-subj="queryInput"]').exists()); // check for presence of query input + return wrapper; }; let abortSpy: jest.SpyInstance; beforeAll(() => { diff --git a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx index ca9029c6c0939c..379e23c6aad94f 100644 --- a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.test.tsx @@ -22,6 +22,15 @@ jest.mock('react-router-dom', () => { }; }); +const mockUseSourcererDataView = jest.fn( + (): { indicesExist: boolean; dataViewId: string | null } => ({ + indicesExist: true, + dataViewId: null, + }) +); +jest.mock('../../containers/sourcerer', () => ({ + useSourcererDataView: () => mockUseSourcererDataView(), +})); const mockedUseIsGroupedNavigationEnabled = jest.fn(); jest.mock('../../components/navigation/helpers', () => ({ @@ -131,4 +140,24 @@ describe('use show timeline', () => { }); }); }); + + describe('sourcererDataView', () => { + it('should show timeline when indices exist', () => { + mockUseSourcererDataView.mockReturnValueOnce({ indicesExist: true, dataViewId: 'test' }); + const { result } = renderHook(() => useShowTimeline()); + expect(result.current).toEqual([true]); + }); + + it('should show timeline when dataViewId is null', () => { + mockUseSourcererDataView.mockReturnValueOnce({ indicesExist: false, dataViewId: null }); + const { result } = renderHook(() => useShowTimeline()); + expect(result.current).toEqual([true]); + }); + + it('should not show timeline when dataViewId is not null and indices does not exist', () => { + mockUseSourcererDataView.mockReturnValueOnce({ indicesExist: false, dataViewId: 'test' }); + const { result } = renderHook(() => useShowTimeline()); + expect(result.current).toEqual([false]); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx index c2dad5ff8f0657..041e36f52a3dbb 100644 --- a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx @@ -5,11 +5,13 @@ * 2.0. */ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { matchPath, useLocation } from 'react-router-dom'; import { getLinksWithHiddenTimeline } from '../../links'; import { useIsGroupedNavigationEnabled } from '../../components/navigation/helpers'; +import { SourcererScopeName } from '../../store/sourcerer/model'; +import { useSourcererDataView } from '../../containers/sourcerer'; const DEPRECATED_HIDDEN_TIMELINE_ROUTES: readonly string[] = [ `/cases/configure`, @@ -34,14 +36,20 @@ const isTimelineHidden = (currentPath: string, isGroupedNavigationEnabled: boole export const useShowTimeline = () => { const isGroupedNavigationEnabled = useIsGroupedNavigationEnabled(); const { pathname } = useLocation(); + const { indicesExist, dataViewId } = useSourcererDataView(SourcererScopeName.timeline); - const [showTimeline, setShowTimeline] = useState( + const [isTimelinePath, setIsTimelinePath] = useState( !isTimelineHidden(pathname, isGroupedNavigationEnabled) ); useEffect(() => { - setShowTimeline(!isTimelineHidden(pathname, isGroupedNavigationEnabled)); + setIsTimelinePath(!isTimelineHidden(pathname, isGroupedNavigationEnabled)); }, [pathname, isGroupedNavigationEnabled]); + const showTimeline = useMemo( + () => isTimelinePath && (dataViewId === null || indicesExist), + [isTimelinePath, indicesExist, dataViewId] + ); + return [showTimeline]; };