From 146eff4b0cb32054c66b90b4db4517e64c296164 Mon Sep 17 00:00:00 2001 From: Kevin Qualters Date: Mon, 4 Jan 2021 16:20:13 -0500 Subject: [PATCH 1/6] Use basePath in getAppOverviewUrl --- .../common/components/header_global/index.tsx | 2 +- .../link_to/redirect_to_overview.tsx | 3 +- .../navigation/breadcrumbs/index.test.ts | 38 ++++++++++++------- .../navigation/breadcrumbs/index.ts | 24 +++++++----- .../common/components/navigation/index.tsx | 6 ++- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx index e8a17d78644d..32710e0d0bde 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx @@ -93,7 +93,7 @@ export const HeaderGlobal = React.memo( - + diff --git a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx index d0cf46bd9052..1cc3d25a3e7f 100644 --- a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx +++ b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx @@ -7,4 +7,5 @@ import { APP_OVERVIEW_PATH } from '../../../../common/constants'; import { appendSearch } from './helpers'; -export const getAppOverviewUrl = (search?: string) => `${APP_OVERVIEW_PATH}${appendSearch(search)}`; +export const getAppOverviewUrl = (basePath: string, search?: string) => + `${basePath}${APP_OVERVIEW_PATH}${appendSearch(search)}`; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index 891e7bfffe86..4e0dd699204b 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -5,7 +5,7 @@ */ import '../../../mock/match_media'; import { encodeIpv6 } from '../../../lib/helpers'; - +import { createStartServicesMock } from '../../../lib/kibana/kibana_react.mock'; import { getBreadcrumbsForRoute, setBreadcrumbs } from '.'; import { HostsTableType } from '../../../../hosts/store/model'; import { RouteSpyState, SiemRouteType } from '../../../utils/route/types'; @@ -29,7 +29,9 @@ const mockDefaultTab = (pageName: string): SiemRouteType | undefined => { return undefined; } }; - +const { + http: { basePath }, +} = createStartServicesMock(); const getMockObject = ( pageName: string, pathName: string, @@ -124,7 +126,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Host breadcrumbs when supplied host pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('hosts', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { @@ -146,7 +149,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Network breadcrumbs when supplied network pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -165,7 +169,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Timelines breadcrumbs when supplied timelines pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('timelines', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -180,7 +185,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Host Details breadcrumbs when supplied a pathname with hostName', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('hosts', '/', hostName), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -201,7 +207,8 @@ describe('Navigation Breadcrumbs', () => { test('should return IP Details breadcrumbs when supplied pathname with ipv4', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', ipv4), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -221,7 +228,8 @@ describe('Navigation Breadcrumbs', () => { test('should return IP Details breadcrumbs when supplied pathname with ipv6', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', ipv6Encoded), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -241,7 +249,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Alerts breadcrumbs when supplied detection pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('detections', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -255,7 +264,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Cases breadcrumbs when supplied case pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('case', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -276,7 +286,8 @@ describe('Navigation Breadcrumbs', () => { ...getMockObject('case', `/${sampleCase.id}`, sampleCase.id), state: { caseTitle: sampleCase.name }, }, - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -294,7 +305,8 @@ describe('Navigation Breadcrumbs', () => { test('should return Admin breadcrumbs when supplied admin pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('administration', '/', undefined), - getUrlForAppMock + getUrlForAppMock, + basePath ); expect(breadcrumbs).toEqual([ { text: 'Security', href: '/app/security/overview' }, @@ -308,7 +320,7 @@ describe('Navigation Breadcrumbs', () => { describe('setBreadcrumbs()', () => { test('should call chrome breadcrumb service with correct breadcrumbs', () => { - setBreadcrumbs(getMockObject('hosts', '/', hostName), chromeMock, getUrlForAppMock); + setBreadcrumbs(getMockObject('hosts', '/', hostName), chromeMock, getUrlForAppMock, basePath); expect(setBreadcrumbsMock).toBeCalledWith([ { text: 'Security', href: '/app/security/overview' }, { diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts index 2964572cb7cf..76adf2c8131f 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts @@ -6,6 +6,7 @@ import { getOr, omit } from 'lodash/fp'; +import { IBasePath } from 'kibana/public'; import { ChromeBreadcrumb } from '../../../../../../../../src/core/public'; import { APP_NAME } from '../../../../../common/constants'; import { StartServices } from '../../../../types'; @@ -32,20 +33,23 @@ import { GetUrlForApp, SearchNavTab } from '../types'; export const setBreadcrumbs = ( spyState: RouteSpyState & TabNavigationProps, chrome: StartServices['chrome'], - getUrlForApp: GetUrlForApp + getUrlForApp: GetUrlForApp, + basePath: IBasePath ) => { - const breadcrumbs = getBreadcrumbsForRoute(spyState, getUrlForApp); + const breadcrumbs = getBreadcrumbsForRoute(spyState, getUrlForApp, basePath); if (breadcrumbs) { chrome.setBreadcrumbs(breadcrumbs); } }; -export const siemRootBreadcrumb: ChromeBreadcrumb[] = [ - { - text: APP_NAME, - href: getAppOverviewUrl(), - }, -]; +const fullSiemRootBreadcrumb = (basePath: IBasePath): ChromeBreadcrumb[] => { + return [ + { + text: APP_NAME, + href: getAppOverviewUrl(basePath.get()), + }, + ]; +}; const isNetworkRoutes = (spyState: RouteSpyState): spyState is NetworkRouteSpyState => spyState != null && spyState.pageName === SecurityPageName.network; @@ -68,9 +72,11 @@ const isAdminRoutes = (spyState: RouteSpyState): spyState is AdministrationRoute // eslint-disable-next-line complexity export const getBreadcrumbsForRoute = ( object: RouteSpyState & TabNavigationProps, - getUrlForApp: GetUrlForApp + getUrlForApp: GetUrlForApp, + basePath: IBasePath ): ChromeBreadcrumb[] | null => { const spyState: RouteSpyState = omit('navTabs', object); + const siemRootBreadcrumb = fullSiemRootBreadcrumb(basePath); if (isHostsRoutes(spyState) && object.navTabs) { const tempNav: SearchNavTab = { urlKey: 'host', isDetailPage: false }; let urlStateKeys = [getOr(tempNav, spyState.pageName, object.navTabs)]; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index db3416866d89..09aa055485cc 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -8,7 +8,7 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; import deepEqual from 'fast-deep-equal'; - +import { IBasePath } from 'kibana/public'; import { useKibana } from '../../lib/kibana'; import { RouteSpyState } from '../../utils/route/types'; import { useRouteSpy } from '../../utils/route/use_route_spy'; @@ -34,6 +34,7 @@ export const SiemNavigationComponent: React.FC< const { chrome, application: { getUrlForApp }, + http: { basePath }, } = useKibana().services; useEffect(() => { @@ -56,7 +57,8 @@ export const SiemNavigationComponent: React.FC< timerange: urlState.timerange, }, chrome, - getUrlForApp + getUrlForApp, + basePath ); } // eslint-disable-next-line react-hooks/exhaustive-deps From d3858c3bb7d01a5c0d3cbd9c978d6f5d86c31d8f Mon Sep 17 00:00:00 2001 From: Kevin Qualters Date: Mon, 4 Jan 2021 21:21:59 -0500 Subject: [PATCH 2/6] Remove unused import and fix broken test --- .../common/components/navigation/index.test.tsx | 13 +++++++++++-- .../public/common/components/navigation/index.tsx | 3 +-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx index f2fbe48c97c8..65ff08020d08 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx @@ -11,6 +11,7 @@ import { CONSTANTS } from '../url_state/constants'; import { SiemNavigationComponent } from './'; import { setBreadcrumbs } from './breadcrumbs'; import { navTabs } from '../../../app/home/home_navigations'; +import { createStartServicesMock } from '../../lib/kibana/kibana_react.mock'; import { HostsTableType } from '../../../hosts/store/model'; import { RouteSpyState } from '../../utils/route/types'; import { SiemNavigationProps, SiemNavigationComponentProps } from './types'; @@ -31,6 +32,9 @@ jest.mock('./breadcrumbs', () => ({ setBreadcrumbs: jest.fn(), })); const mockGetUrlForApp = jest.fn(); +const { + http: { basePath: mockBasePath }, +} = createStartServicesMock(); jest.mock('../../lib/kibana', () => { return { useKibana: () => ({ @@ -40,6 +44,9 @@ jest.mock('../../lib/kibana', () => { navigateToApp: jest.fn(), getUrlForApp: mockGetUrlForApp, }, + http: { + basePath: mockBasePath, + }, }, }), }; @@ -185,7 +192,8 @@ describe('SIEM Navigation', () => { }, }, undefined, - mockGetUrlForApp + mockGetUrlForApp, + mockBasePath ); }); test('it calls setBreadcrumbs with correct path on update', () => { @@ -285,7 +293,8 @@ describe('SIEM Navigation', () => { }, }, undefined, - mockGetUrlForApp + mockGetUrlForApp, + mockBasePath ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index 09aa055485cc..fbe32020f100 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -8,7 +8,6 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; import deepEqual from 'fast-deep-equal'; -import { IBasePath } from 'kibana/public'; import { useKibana } from '../../lib/kibana'; import { RouteSpyState } from '../../utils/route/types'; import { useRouteSpy } from '../../utils/route/use_route_spy'; @@ -62,7 +61,7 @@ export const SiemNavigationComponent: React.FC< ); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [chrome, pageName, pathName, search, navTabs, urlState, state]); + }, [chrome, pageName, pathName, search, navTabs, urlState, state, basePath]); return ( Date: Tue, 5 Jan 2021 12:13:15 -0500 Subject: [PATCH 3/6] Use getUrlForApp rather than basePath --- .../link_to/redirect_to_overview.tsx | 5 +- .../navigation/breadcrumbs/index.test.ts | 59 ++++++++----------- .../navigation/breadcrumbs/index.ts | 40 +++++-------- .../components/navigation/index.test.tsx | 14 +---- .../common/components/navigation/index.tsx | 6 +- 5 files changed, 46 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx index 1cc3d25a3e7f..9bf2d28f3f33 100644 --- a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx +++ b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APP_OVERVIEW_PATH } from '../../../../common/constants'; import { appendSearch } from './helpers'; -export const getAppOverviewUrl = (basePath: string, search?: string) => - `${basePath}${APP_OVERVIEW_PATH}${appendSearch(search)}`; +export const getAppOverviewUrl = (overviewPath: string, search?: string) => + `${overviewPath}${appendSearch(search)}`; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index 4e0dd699204b..c2f1b599b460 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -5,7 +5,6 @@ */ import '../../../mock/match_media'; import { encodeIpv6 } from '../../../lib/helpers'; -import { createStartServicesMock } from '../../../lib/kibana/kibana_react.mock'; import { getBreadcrumbsForRoute, setBreadcrumbs } from '.'; import { HostsTableType } from '../../../../hosts/store/model'; import { RouteSpyState, SiemRouteType } from '../../../utils/route/types'; @@ -29,9 +28,7 @@ const mockDefaultTab = (pageName: string): SiemRouteType | undefined => { return undefined; } }; -const { - http: { basePath }, -} = createStartServicesMock(); + const getMockObject = ( pageName: string, pathName: string, @@ -126,12 +123,11 @@ describe('Navigation Breadcrumbs', () => { test('should return Host breadcrumbs when supplied host pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('hosts', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ { - href: '/app/security/overview', + href: 'securitySolutionoverview', text: 'Security', }, { @@ -149,11 +145,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Network breadcrumbs when supplied network pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -169,11 +164,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Timelines breadcrumbs when supplied timelines pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('timelines', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Timelines', href: @@ -185,11 +179,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Host Details breadcrumbs when supplied a pathname with hostName', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('hosts', '/', hostName), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Hosts', href: @@ -207,11 +200,10 @@ describe('Navigation Breadcrumbs', () => { test('should return IP Details breadcrumbs when supplied pathname with ipv4', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', ipv4), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -228,11 +220,10 @@ describe('Navigation Breadcrumbs', () => { test('should return IP Details breadcrumbs when supplied pathname with ipv6', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('network', '/', ipv6Encoded), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -249,11 +240,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Alerts breadcrumbs when supplied detection pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('detections', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Detections', href: @@ -264,11 +254,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Cases breadcrumbs when supplied case pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('case', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Cases', href: @@ -286,11 +275,10 @@ describe('Navigation Breadcrumbs', () => { ...getMockObject('case', `/${sampleCase.id}`, sampleCase.id), state: { caseTitle: sampleCase.name }, }, - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Cases', href: @@ -305,11 +293,10 @@ describe('Navigation Breadcrumbs', () => { test('should return Admin breadcrumbs when supplied admin pathname', () => { const breadcrumbs = getBreadcrumbsForRoute( getMockObject('administration', '/', undefined), - getUrlForAppMock, - basePath + getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Administration', href: 'securitySolution:administration', @@ -320,9 +307,9 @@ describe('Navigation Breadcrumbs', () => { describe('setBreadcrumbs()', () => { test('should call chrome breadcrumb service with correct breadcrumbs', () => { - setBreadcrumbs(getMockObject('hosts', '/', hostName), chromeMock, getUrlForAppMock, basePath); + setBreadcrumbs(getMockObject('hosts', '/', hostName), chromeMock, getUrlForAppMock); expect(setBreadcrumbsMock).toBeCalledWith([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Hosts', href: diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts index 76adf2c8131f..410fdd0cb4a5 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts @@ -6,9 +6,8 @@ import { getOr, omit } from 'lodash/fp'; -import { IBasePath } from 'kibana/public'; import { ChromeBreadcrumb } from '../../../../../../../../src/core/public'; -import { APP_NAME } from '../../../../../common/constants'; +import { APP_NAME, APP_ID } from '../../../../../common/constants'; import { StartServices } from '../../../../types'; import { getBreadcrumbs as getHostDetailsBreadcrumbs } from '../../../../hosts/pages/details/utils'; import { getBreadcrumbs as getIPDetailsBreadcrumbs } from '../../../../network/pages/details'; @@ -33,24 +32,14 @@ import { GetUrlForApp, SearchNavTab } from '../types'; export const setBreadcrumbs = ( spyState: RouteSpyState & TabNavigationProps, chrome: StartServices['chrome'], - getUrlForApp: GetUrlForApp, - basePath: IBasePath + getUrlForApp: GetUrlForApp ) => { - const breadcrumbs = getBreadcrumbsForRoute(spyState, getUrlForApp, basePath); + const breadcrumbs = getBreadcrumbsForRoute(spyState, getUrlForApp); if (breadcrumbs) { chrome.setBreadcrumbs(breadcrumbs); } }; -const fullSiemRootBreadcrumb = (basePath: IBasePath): ChromeBreadcrumb[] => { - return [ - { - text: APP_NAME, - href: getAppOverviewUrl(basePath.get()), - }, - ]; -}; - const isNetworkRoutes = (spyState: RouteSpyState): spyState is NetworkRouteSpyState => spyState != null && spyState.pageName === SecurityPageName.network; @@ -72,11 +61,14 @@ const isAdminRoutes = (spyState: RouteSpyState): spyState is AdministrationRoute // eslint-disable-next-line complexity export const getBreadcrumbsForRoute = ( object: RouteSpyState & TabNavigationProps, - getUrlForApp: GetUrlForApp, - basePath: IBasePath + getUrlForApp: GetUrlForApp ): ChromeBreadcrumb[] | null => { const spyState: RouteSpyState = omit('navTabs', object); - const siemRootBreadcrumb = fullSiemRootBreadcrumb(basePath); + const overviewPath = getUrlForApp(APP_ID, { path: SecurityPageName.overview }); + const siemRootBreadcrumb: ChromeBreadcrumb = { + text: APP_NAME, + href: getAppOverviewUrl(overviewPath), + }; if (isHostsRoutes(spyState) && object.navTabs) { const tempNav: SearchNavTab = { urlKey: 'host', isDetailPage: false }; let urlStateKeys = [getOr(tempNav, spyState.pageName, object.navTabs)]; @@ -84,7 +76,7 @@ export const getBreadcrumbsForRoute = ( urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getHostDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -102,7 +94,7 @@ export const getBreadcrumbsForRoute = ( urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getIPDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -121,7 +113,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getDetectionRulesBreadcrumbs( spyState, urlStateKeys.reduce( @@ -140,7 +132,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getCaseDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -159,7 +151,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getTimelinesBreadcrumbs( spyState, urlStateKeys.reduce( @@ -179,7 +171,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getAdminBreadcrumbs( spyState, urlStateKeys.reduce( @@ -198,7 +190,7 @@ export const getBreadcrumbsForRoute = ( object.navTabs[spyState.pageName] ) { return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, { text: object.navTabs[spyState.pageName].name, href: '', diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx index 65ff08020d08..6c2038cf252b 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx @@ -11,7 +11,6 @@ import { CONSTANTS } from '../url_state/constants'; import { SiemNavigationComponent } from './'; import { setBreadcrumbs } from './breadcrumbs'; import { navTabs } from '../../../app/home/home_navigations'; -import { createStartServicesMock } from '../../lib/kibana/kibana_react.mock'; import { HostsTableType } from '../../../hosts/store/model'; import { RouteSpyState } from '../../utils/route/types'; import { SiemNavigationProps, SiemNavigationComponentProps } from './types'; @@ -32,9 +31,7 @@ jest.mock('./breadcrumbs', () => ({ setBreadcrumbs: jest.fn(), })); const mockGetUrlForApp = jest.fn(); -const { - http: { basePath: mockBasePath }, -} = createStartServicesMock(); + jest.mock('../../lib/kibana', () => { return { useKibana: () => ({ @@ -44,9 +41,6 @@ jest.mock('../../lib/kibana', () => { navigateToApp: jest.fn(), getUrlForApp: mockGetUrlForApp, }, - http: { - basePath: mockBasePath, - }, }, }), }; @@ -192,8 +186,7 @@ describe('SIEM Navigation', () => { }, }, undefined, - mockGetUrlForApp, - mockBasePath + mockGetUrlForApp ); }); test('it calls setBreadcrumbs with correct path on update', () => { @@ -293,8 +286,7 @@ describe('SIEM Navigation', () => { }, }, undefined, - mockGetUrlForApp, - mockBasePath + mockGetUrlForApp ); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index fbe32020f100..4e53a5dc02de 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -33,7 +33,6 @@ export const SiemNavigationComponent: React.FC< const { chrome, application: { getUrlForApp }, - http: { basePath }, } = useKibana().services; useEffect(() => { @@ -56,12 +55,11 @@ export const SiemNavigationComponent: React.FC< timerange: urlState.timerange, }, chrome, - getUrlForApp, - basePath + getUrlForApp ); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [chrome, pageName, pathName, search, navTabs, urlState, state, basePath]); + }, [chrome, pageName, pathName, search, navTabs, urlState, state]); return ( Date: Tue, 5 Jan 2021 12:23:54 -0500 Subject: [PATCH 4/6] Use getUrlForApp on logo link --- .../public/common/components/header_global/index.tsx | 9 +++++++-- .../public/common/components/navigation/index.test.tsx | 1 - .../public/common/components/navigation/index.tsx | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx index 32710e0d0bde..256e2341c756 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx @@ -72,7 +72,9 @@ export const HeaderGlobal = React.memo( const { timelineFullScreen } = useTimelineFullScreen(); const search = useGetUrlSearch(navTabs.overview); const { application, http } = useKibana().services; - const { navigateToApp } = application; + const { navigateToApp, getUrlForApp } = application; + const overviewPath = getUrlForApp(APP_ID, { path: SecurityPageName.overview }); + const basePath = http.basePath.get(); const goToOverview = useCallback( (ev) => { @@ -93,7 +95,10 @@ export const HeaderGlobal = React.memo( - + diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx index 6c2038cf252b..f2fbe48c97c8 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx @@ -31,7 +31,6 @@ jest.mock('./breadcrumbs', () => ({ setBreadcrumbs: jest.fn(), })); const mockGetUrlForApp = jest.fn(); - jest.mock('../../lib/kibana', () => { return { useKibana: () => ({ diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index 4e53a5dc02de..db3416866d89 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -8,6 +8,7 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; import deepEqual from 'fast-deep-equal'; + import { useKibana } from '../../lib/kibana'; import { RouteSpyState } from '../../utils/route/types'; import { useRouteSpy } from '../../utils/route/use_route_spy'; From 5f1709aa77149e177117a1e977aebf95b041182f Mon Sep 17 00:00:00 2001 From: Kevin Qualters Date: Tue, 5 Jan 2021 12:58:24 -0500 Subject: [PATCH 5/6] Memoize overview url variables --- .../common/components/header_global/index.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx index 256e2341c756..5bb1081de22e 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx @@ -6,7 +6,7 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; import { pickBy } from 'lodash/fp'; -import React, { forwardRef, useCallback } from 'react'; +import React, { forwardRef, useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { OutPortal } from 'react-reverse-portal'; @@ -73,7 +73,14 @@ export const HeaderGlobal = React.memo( const search = useGetUrlSearch(navTabs.overview); const { application, http } = useKibana().services; const { navigateToApp, getUrlForApp } = application; - const overviewPath = getUrlForApp(APP_ID, { path: SecurityPageName.overview }); + const overviewPath = useMemo( + () => getUrlForApp(APP_ID, { path: SecurityPageName.overview }), + [getUrlForApp] + ); + const overviewHref = useMemo(() => getAppOverviewUrl(overviewPath, search), [ + overviewPath, + search, + ]); const basePath = http.basePath.get(); const goToOverview = useCallback( @@ -95,10 +102,7 @@ export const HeaderGlobal = React.memo( - + From 4737cee34c0931e922457e54d48f1fb580ac2feb Mon Sep 17 00:00:00 2001 From: Kevin Qualters Date: Wed, 6 Jan 2021 10:16:12 -0500 Subject: [PATCH 6/6] Add comment explaining getUrlForAppMock has different format --- .../common/components/navigation/breadcrumbs/index.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index c2f1b599b460..f219f9bef5f8 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -109,6 +109,7 @@ const getMockObject = ( sourcerer: {}, }); +// The string returned is different from what getUrlForApp returns, but does not matter for the purposes of this test. const getUrlForAppMock = (appId: string, options?: { path?: string; absolute?: boolean }) => `${appId}${options?.path ?? ''}`;