diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts
index ef3bf54053b5c..890072ab42eb9 100644
--- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts
@@ -13,6 +13,7 @@ import { ExternalUrl } from '../shared/enterprise_search_url';
*/
export const mockKibanaContext = {
http: httpServiceMock.createSetupContract(),
+ navigateToUrl: jest.fn(),
setBreadcrumbs: jest.fn(),
setDocTitle: jest.fn(),
config: { host: 'http://localhost:3002' },
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx
index 7ebd35ff35ee1..5856a13bf75b7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx
@@ -36,7 +36,6 @@ export const AppSearch: React.FC = () => {
- {/* Kibana displays a blank page on redirect if this isn't included */}
);
@@ -50,8 +49,7 @@ export const AppSearch: React.FC = () => {
}>
- {/* For some reason a Redirect to /engines just doesn't work here - it shows a blank page */}
-
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx
index f3ccbc126ae62..1b1f9ae43e7c1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx
@@ -9,7 +9,13 @@ import ReactDOM from 'react-dom';
import { Router } from 'react-router-dom';
import { I18nProvider } from '@kbn/i18n/react';
-import { CoreStart, AppMountParameters, HttpSetup, ChromeBreadcrumb } from 'src/core/public';
+import {
+ AppMountParameters,
+ CoreStart,
+ ApplicationStart,
+ HttpSetup,
+ ChromeBreadcrumb,
+} from 'src/core/public';
import { ClientConfigType, ClientData, PluginsSetup } from '../plugin';
import { LicenseProvider } from './shared/licensing';
import { IExternalUrl } from './shared/enterprise_search_url';
@@ -18,6 +24,7 @@ export interface IKibanaContext {
config: { host?: string };
externalUrl: IExternalUrl;
http: HttpSetup;
+ navigateToUrl: ApplicationStart['navigateToUrl'];
setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void;
setDocTitle(title: string): void;
}
@@ -44,6 +51,7 @@ export const renderApp = (
value={{
config,
http: core.http,
+ navigateToUrl: core.application.navigateToUrl,
externalUrl: data.externalUrl,
setBreadcrumbs: core.chrome.setBreadcrumbs,
setDocTitle: core.chrome.docTitle.change,
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts
index 0f34bbb6b65bc..9e86b239432a7 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts
@@ -4,140 +4,121 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- generateBreadcrumb,
- appSearchBreadcrumbs,
- enterpriseSearchBreadcrumbs,
- workplaceSearchBreadcrumbs,
-} from './generate_breadcrumbs';
-
-import { mockHistory as mockHistoryUntyped } from '../../__mocks__';
-const mockHistory = mockHistoryUntyped as any;
+import '../../__mocks__/shallow_usecontext.mock';
+import '../../__mocks__/react_router_history.mock';
+import { mockKibanaContext, mockHistory } from '../../__mocks__';
jest.mock('../react_router_helpers', () => ({ letBrowserHandleEvent: jest.fn(() => false) }));
import { letBrowserHandleEvent } from '../react_router_helpers';
-describe('generateBreadcrumb', () => {
+import {
+ useBreadcrumbs,
+ useEnterpriseSearchBreadcrumbs,
+ useAppSearchBreadcrumbs,
+ useWorkplaceSearchBreadcrumbs,
+} from './generate_breadcrumbs';
+
+describe('useBreadcrumbs', () => {
beforeEach(() => {
jest.clearAllMocks();
});
- it("creates a breadcrumb object matching EUI's breadcrumb type", () => {
- const breadcrumb = generateBreadcrumb({
- text: 'Hello World',
- path: '/hello_world',
- history: mockHistory,
- });
- expect(breadcrumb).toEqual({
- text: 'Hello World',
- href: '/enterprise_search/hello_world',
- onClick: expect.any(Function),
- });
+ it('accepts an array of breadcrumbs and to the array correctly injects SPA link navigation props', () => {
+ const breadcrumb = useBreadcrumbs([
+ {
+ text: 'Hello',
+ path: '/hello',
+ },
+ {
+ text: 'World',
+ path: '/world',
+ },
+ ]);
+ expect(breadcrumb).toEqual([
+ {
+ text: 'Hello',
+ href: '/enterprise_search/hello',
+ onClick: expect.any(Function),
+ },
+ {
+ text: 'World',
+ href: '/enterprise_search/world',
+ onClick: expect.any(Function),
+ },
+ ]);
});
it('prevents default navigation and uses React Router history on click', () => {
- const breadcrumb = generateBreadcrumb({ text: '', path: '/', history: mockHistory }) as any;
+ const breadcrumb = useBreadcrumbs([{ text: '', path: '/' }])[0] as any;
const event = { preventDefault: jest.fn() };
breadcrumb.onClick(event);
- expect(mockHistory.push).toHaveBeenCalled();
+ expect(mockKibanaContext.navigateToUrl).toHaveBeenCalled();
+ expect(mockHistory.createHref).toHaveBeenCalled();
expect(event.preventDefault).toHaveBeenCalled();
});
it('does not prevent default browser behavior on new tab/window clicks', () => {
- const breadcrumb = generateBreadcrumb({ text: '', path: '/', history: mockHistory }) as any;
+ const breadcrumb = useBreadcrumbs([{ text: '', path: '/' }])[0] as any;
(letBrowserHandleEvent as jest.Mock).mockImplementationOnce(() => true);
breadcrumb.onClick();
- expect(mockHistory.push).not.toHaveBeenCalled();
+ expect(mockKibanaContext.navigateToUrl).not.toHaveBeenCalled();
});
it('does not generate link behavior if path is excluded', () => {
- const breadcrumb = generateBreadcrumb({ text: 'Unclickable breadcrumb' });
+ const breadcrumb = useBreadcrumbs([{ text: 'Unclickable breadcrumb' }])[0];
expect(breadcrumb.href).toBeUndefined();
expect(breadcrumb.onClick).toBeUndefined();
});
});
-describe('enterpriseSearchBreadcrumbs', () => {
- const breadCrumbs = [
- {
- text: 'Page 1',
- path: '/page1',
- },
- {
- text: 'Page 2',
- path: '/page2',
- },
- ];
-
+describe('useEnterpriseSearchBreadcrumbs', () => {
beforeEach(() => {
jest.clearAllMocks();
});
- const subject = () => enterpriseSearchBreadcrumbs(mockHistory)(breadCrumbs);
+ it('builds a chain of breadcrumbs with Enterprise Search at the root', () => {
+ const breadcrumbs = [
+ {
+ text: 'Page 1',
+ path: '/page1',
+ },
+ {
+ text: 'Page 2',
+ path: '/page2',
+ },
+ ];
- it('Builds a chain of breadcrumbs with Enterprise Search at the root', () => {
- expect(subject()).toEqual([
+ expect(useEnterpriseSearchBreadcrumbs(breadcrumbs)).toEqual([
{
text: 'Enterprise Search',
},
{
+ text: 'Page 1',
href: '/enterprise_search/page1',
onClick: expect.any(Function),
- text: 'Page 1',
},
{
+ text: 'Page 2',
href: '/enterprise_search/page2',
onClick: expect.any(Function),
- text: 'Page 2',
},
]);
});
it('shows just the root if breadcrumbs is empty', () => {
- expect(enterpriseSearchBreadcrumbs(mockHistory)()).toEqual([
+ expect(useEnterpriseSearchBreadcrumbs()).toEqual([
{
text: 'Enterprise Search',
},
]);
});
-
- describe('links', () => {
- const eventMock = {
- preventDefault: jest.fn(),
- } as any;
-
- it('has Enterprise Search text first', () => {
- expect(subject()[0].onClick).toBeUndefined();
- });
-
- it('has a link to page 1 second', () => {
- (subject()[1] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page1');
- });
-
- it('has a link to page 2 last', () => {
- (subject()[2] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page2');
- });
- });
});
-describe('appSearchBreadcrumbs', () => {
- const breadCrumbs = [
- {
- text: 'Page 1',
- path: '/page1',
- },
- {
- text: 'Page 2',
- path: '/page2',
- },
- ];
-
+describe('useAppSearchBreadcrumbs', () => {
beforeEach(() => {
jest.clearAllMocks();
mockHistory.createHref.mockImplementation(
@@ -145,82 +126,55 @@ describe('appSearchBreadcrumbs', () => {
);
});
- const subject = () => appSearchBreadcrumbs(mockHistory)(breadCrumbs);
-
it('Builds a chain of breadcrumbs with Enterprise Search and App Search at the root', () => {
- expect(subject()).toEqual([
+ const breadcrumbs = [
+ {
+ text: 'Page 1',
+ path: '/page1',
+ },
+ {
+ text: 'Page 2',
+ path: '/page2',
+ },
+ ];
+
+ expect(useAppSearchBreadcrumbs(breadcrumbs)).toEqual([
{
text: 'Enterprise Search',
},
{
+ text: 'App Search',
href: '/enterprise_search/app_search/',
onClick: expect.any(Function),
- text: 'App Search',
},
{
+ text: 'Page 1',
href: '/enterprise_search/app_search/page1',
onClick: expect.any(Function),
- text: 'Page 1',
},
{
+ text: 'Page 2',
href: '/enterprise_search/app_search/page2',
onClick: expect.any(Function),
- text: 'Page 2',
},
]);
});
it('shows just the root if breadcrumbs is empty', () => {
- expect(appSearchBreadcrumbs(mockHistory)()).toEqual([
+ expect(useAppSearchBreadcrumbs()).toEqual([
{
text: 'Enterprise Search',
},
{
+ text: 'App Search',
href: '/enterprise_search/app_search/',
onClick: expect.any(Function),
- text: 'App Search',
},
]);
});
-
- describe('links', () => {
- const eventMock = {
- preventDefault: jest.fn(),
- } as any;
-
- it('has Enterprise Search text first', () => {
- expect(subject()[0].onClick).toBeUndefined();
- });
-
- it('has a link to App Search second', () => {
- (subject()[1] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/');
- });
-
- it('has a link to page 1 third', () => {
- (subject()[2] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page1');
- });
-
- it('has a link to page 2 last', () => {
- (subject()[3] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page2');
- });
- });
});
-describe('workplaceSearchBreadcrumbs', () => {
- const breadCrumbs = [
- {
- text: 'Page 1',
- path: '/page1',
- },
- {
- text: 'Page 2',
- path: '/page2',
- },
- ];
-
+describe('useWorkplaceSearchBreadcrumbs', () => {
beforeEach(() => {
jest.clearAllMocks();
mockHistory.createHref.mockImplementation(
@@ -228,66 +182,50 @@ describe('workplaceSearchBreadcrumbs', () => {
);
});
- const subject = () => workplaceSearchBreadcrumbs(mockHistory)(breadCrumbs);
-
it('Builds a chain of breadcrumbs with Enterprise Search and Workplace Search at the root', () => {
- expect(subject()).toEqual([
+ const breadcrumbs = [
+ {
+ text: 'Page 1',
+ path: '/page1',
+ },
+ {
+ text: 'Page 2',
+ path: '/page2',
+ },
+ ];
+
+ expect(useWorkplaceSearchBreadcrumbs(breadcrumbs)).toEqual([
{
text: 'Enterprise Search',
},
{
+ text: 'Workplace Search',
href: '/enterprise_search/workplace_search/',
onClick: expect.any(Function),
- text: 'Workplace Search',
},
{
+ text: 'Page 1',
href: '/enterprise_search/workplace_search/page1',
onClick: expect.any(Function),
- text: 'Page 1',
},
{
+ text: 'Page 2',
href: '/enterprise_search/workplace_search/page2',
onClick: expect.any(Function),
- text: 'Page 2',
},
]);
});
it('shows just the root if breadcrumbs is empty', () => {
- expect(workplaceSearchBreadcrumbs(mockHistory)()).toEqual([
+ expect(useWorkplaceSearchBreadcrumbs()).toEqual([
{
text: 'Enterprise Search',
},
{
+ text: 'Workplace Search',
href: '/enterprise_search/workplace_search/',
onClick: expect.any(Function),
- text: 'Workplace Search',
},
]);
});
-
- describe('links', () => {
- const eventMock = {
- preventDefault: jest.fn(),
- } as any;
-
- it('has Enterprise Search text first', () => {
- expect(subject()[0].onClick).toBeUndefined();
- });
-
- it('has a link to Workplace Search second', () => {
- (subject()[1] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/');
- });
-
- it('has a link to page 1 third', () => {
- (subject()[2] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page1');
- });
-
- it('has a link to page 2 last', () => {
- (subject()[3] as any).onClick(eventMock);
- expect(mockHistory.push).toHaveBeenCalledWith('/page2');
- });
- });
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
index 82c0f78fb853f..6eab936719d01 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
@@ -4,8 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { useContext } from 'react';
+import { useHistory } from 'react-router-dom';
import { EuiBreadcrumb } from '@elastic/eui';
-import { History } from 'history';
+
+import { KibanaContext, IKibanaContext } from '../../index';
import {
ENTERPRISE_SEARCH_PLUGIN,
@@ -20,50 +23,46 @@ import { letBrowserHandleEvent } from '../react_router_helpers';
* https://elastic.github.io/eui/#/navigation/breadcrumbs
*/
-interface IGenerateBreadcrumbProps {
+interface IBreadcrumb {
text: string;
path?: string;
- history?: History;
}
+export type TBreadcrumbs = IBreadcrumb[];
+
+export const useBreadcrumbs = (breadcrumbs: TBreadcrumbs) => {
+ const history = useHistory();
+ const { navigateToUrl } = useContext(KibanaContext) as IKibanaContext;
+
+ return breadcrumbs.map(({ text, path }) => {
+ const breadcrumb = { text } as EuiBreadcrumb;
-export const generateBreadcrumb = ({ text, path, history }: IGenerateBreadcrumbProps) => {
- const breadcrumb = { text } as EuiBreadcrumb;
+ if (path) {
+ const href = history.createHref({ pathname: path }) as string;
- if (path && history) {
- breadcrumb.href = history.createHref({ pathname: path });
- breadcrumb.onClick = (event) => {
- if (letBrowserHandleEvent(event)) return;
- event.preventDefault();
- history.push(path);
- };
- }
+ breadcrumb.href = href;
+ breadcrumb.onClick = (event) => {
+ if (letBrowserHandleEvent(event)) return;
+ event.preventDefault();
+ navigateToUrl(href);
+ };
+ }
- return breadcrumb;
+ return breadcrumb;
+ });
};
/**
* Product-specific breadcrumb helpers
*/
-export type TBreadcrumbs = IGenerateBreadcrumbProps[];
+export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: TBreadcrumbs = []) =>
+ useBreadcrumbs([{ text: ENTERPRISE_SEARCH_PLUGIN.NAME }, ...breadcrumbs]);
-export const enterpriseSearchBreadcrumbs = (history: History) => (
- breadcrumbs: TBreadcrumbs = []
-) => [
- generateBreadcrumb({ text: ENTERPRISE_SEARCH_PLUGIN.NAME }),
- ...breadcrumbs.map(({ text, path }: IGenerateBreadcrumbProps) =>
- generateBreadcrumb({ text, path, history })
- ),
-];
-
-export const appSearchBreadcrumbs = (history: History) => (breadcrumbs: TBreadcrumbs = []) =>
- enterpriseSearchBreadcrumbs(history)([
- { text: APP_SEARCH_PLUGIN.NAME, path: '/' },
- ...breadcrumbs,
- ]);
+export const useAppSearchBreadcrumbs = (breadcrumbs: TBreadcrumbs = []) =>
+ useEnterpriseSearchBreadcrumbs([{ text: APP_SEARCH_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
-export const workplaceSearchBreadcrumbs = (history: History) => (breadcrumbs: TBreadcrumbs = []) =>
- enterpriseSearchBreadcrumbs(history)([
+export const useWorkplaceSearchBreadcrumbs = (breadcrumbs: TBreadcrumbs = []) =>
+ useEnterpriseSearchBreadcrumbs([
{ text: WORKPLACE_SEARCH_PLUGIN.NAME, path: '/' },
...breadcrumbs,
]);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx
index aba0b250e56c0..bda816c9a5554 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx
@@ -4,16 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import '../../__mocks__/shallow_usecontext.mock';
+import '../../__mocks__/react_router_history.mock';
+
import React from 'react';
-import '../../__mocks__/react_router_history.mock';
import { mockKibanaContext, mountWithKibanaContext } from '../../__mocks__';
jest.mock('./generate_breadcrumbs', () => ({
- appSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs),
- workplaceSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs),
+ useAppSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs),
+ useWorkplaceSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs),
}));
-import { appSearchBreadcrumbs, workplaceSearchBreadcrumbs } from './generate_breadcrumbs';
+import { useAppSearchBreadcrumbs, useWorkplaceSearchBreadcrumbs } from './generate_breadcrumbs';
jest.mock('./generate_title', () => ({
appSearchTitle: jest.fn((title: any) => title),
@@ -23,62 +25,55 @@ import { appSearchTitle, workplaceSearchTitle } from './generate_title';
import { SetAppSearchChrome, SetWorkplaceSearchChrome } from './';
-describe('SetAppSearchChrome', () => {
+describe('Set Kibana Chrome helpers', () => {
beforeEach(() => {
jest.clearAllMocks();
});
afterEach(() => {
- expect(appSearchBreadcrumbs).toHaveBeenCalled();
- expect(appSearchTitle).toHaveBeenCalled();
- });
-
- it('sets breadcrumbs and document title', () => {
- mountWithKibanaContext();
-
- expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([
- {
- text: 'Engines',
- path: '/current-path',
- },
- ]);
- expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith(['Engines']);
+ expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalled();
+ expect(mockKibanaContext.setDocTitle).toHaveBeenCalled();
});
- it('sets empty breadcrumbs and document title when isRoot is true', () => {
- mountWithKibanaContext();
-
- expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([]);
- expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith([]);
+ describe('SetAppSearchChrome', () => {
+ it('sets breadcrumbs and document title', () => {
+ mountWithKibanaContext();
+
+ expect(appSearchTitle).toHaveBeenCalledWith(['Engines']);
+ expect(useAppSearchBreadcrumbs).toHaveBeenCalledWith([
+ {
+ text: 'Engines',
+ path: '/current-path',
+ },
+ ]);
+ });
+
+ it('sets empty breadcrumbs and document title when isRoot is true', () => {
+ mountWithKibanaContext();
+
+ expect(appSearchTitle).toHaveBeenCalledWith([]);
+ expect(useAppSearchBreadcrumbs).toHaveBeenCalledWith([]);
+ });
});
-});
-
-describe('SetWorkplaceSearchChrome', () => {
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
- afterEach(() => {
- expect(workplaceSearchBreadcrumbs).toHaveBeenCalled();
- expect(workplaceSearchTitle).toHaveBeenCalled();
- });
-
- it('sets breadcrumbs and document title', () => {
- mountWithKibanaContext();
-
- expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([
- {
- text: 'Sources',
- path: '/current-path',
- },
- ]);
- expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith(['Sources']);
- });
-
- it('sets empty breadcrumbs and document title when isRoot is true', () => {
- mountWithKibanaContext();
- expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([]);
- expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith([]);
+ describe('SetWorkplaceSearchChrome', () => {
+ it('sets breadcrumbs and document title', () => {
+ mountWithKibanaContext();
+
+ expect(workplaceSearchTitle).toHaveBeenCalledWith(['Sources']);
+ expect(useWorkplaceSearchBreadcrumbs).toHaveBeenCalledWith([
+ {
+ text: 'Sources',
+ path: '/current-path',
+ },
+ ]);
+ });
+
+ it('sets empty breadcrumbs and document title when isRoot is true', () => {
+ mountWithKibanaContext();
+
+ expect(workplaceSearchTitle).toHaveBeenCalledWith([]);
+ expect(useWorkplaceSearchBreadcrumbs).toHaveBeenCalledWith([]);
+ });
});
});
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
index 59e83a2cb13c2..43db93c1583d1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
@@ -7,10 +7,11 @@
import React, { useContext, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { EuiBreadcrumb } from '@elastic/eui';
+
import { KibanaContext, IKibanaContext } from '../../index';
import {
- appSearchBreadcrumbs,
- workplaceSearchBreadcrumbs,
+ useAppSearchBreadcrumbs,
+ useWorkplaceSearchBreadcrumbs,
TBreadcrumbs,
} from './generate_breadcrumbs';
import { appSearchTitle, workplaceSearchTitle, TTitle } from './generate_title';
@@ -36,12 +37,15 @@ export const SetAppSearchChrome: React.FC = ({ text, isRoot }
const history = useHistory();
const { setBreadcrumbs, setDocTitle } = useContext(KibanaContext) as IKibanaContext;
- const crumb = isRoot ? [] : [{ text, path: history.location.pathname }];
const title = isRoot ? [] : [text];
+ const docTitle = appSearchTitle(title as TTitle | []);
+
+ const crumb = isRoot ? [] : [{ text, path: history.location.pathname }];
+ const breadcrumbs = useAppSearchBreadcrumbs(crumb as TBreadcrumbs | []);
useEffect(() => {
- setBreadcrumbs(appSearchBreadcrumbs(history)(crumb as TBreadcrumbs | []));
- setDocTitle(appSearchTitle(title as TTitle | []));
+ setBreadcrumbs(breadcrumbs);
+ setDocTitle(docTitle);
}, []);
return null;
@@ -51,12 +55,15 @@ export const SetWorkplaceSearchChrome: React.FC = ({ text, is
const history = useHistory();
const { setBreadcrumbs, setDocTitle } = useContext(KibanaContext) as IKibanaContext;
- const crumb = isRoot ? [] : [{ text, path: history.location.pathname }];
const title = isRoot ? [] : [text];
+ const docTitle = workplaceSearchTitle(title as TTitle | []);
+
+ const crumb = isRoot ? [] : [{ text, path: history.location.pathname }];
+ const breadcrumbs = useWorkplaceSearchBreadcrumbs(crumb as TBreadcrumbs | []);
useEffect(() => {
- setBreadcrumbs(workplaceSearchBreadcrumbs(history)(crumb as TBreadcrumbs | []));
- setDocTitle(workplaceSearchTitle(title as TTitle | []));
+ setBreadcrumbs(breadcrumbs);
+ setDocTitle(docTitle);
}, []);
return null;
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
index 76ee8293f2c8b..063118f94cd19 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.test.tsx
@@ -4,12 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import '../../__mocks__/shallow_usecontext.mock';
+import '../../__mocks__/react_router_history.mock';
+
import React from 'react';
import { shallow, mount } from 'enzyme';
import { EuiLink, EuiButton } from '@elastic/eui';
-import '../../__mocks__/react_router_history.mock';
-import { mockHistory } from '../../__mocks__';
+import { mockKibanaContext, mockHistory } from '../../__mocks__';
import { EuiReactRouterLink, EuiReactRouterButton } from './eui_link';
@@ -59,7 +61,7 @@ describe('EUI & React Router Component Helpers', () => {
wrapper.find(EuiLink).simulate('click', simulatedEvent);
expect(simulatedEvent.preventDefault).toHaveBeenCalled();
- expect(mockHistory.push).toHaveBeenCalled();
+ expect(mockKibanaContext.navigateToUrl).toHaveBeenCalled();
});
it('does not prevent default browser behavior on new tab/window clicks', () => {
@@ -71,7 +73,7 @@ describe('EUI & React Router Component Helpers', () => {
};
wrapper.find(EuiLink).simulate('click', simulatedEvent);
- expect(mockHistory.push).not.toHaveBeenCalled();
+ expect(mockKibanaContext.navigateToUrl).not.toHaveBeenCalled();
});
it('calls inherited onClick actions in addition to default navigation', () => {
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
index b53b2f2b3b650..7221a61d0997b 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx
@@ -4,10 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useContext } from 'react';
import { useHistory } from 'react-router-dom';
import { EuiLink, EuiButton, EuiButtonProps, EuiLinkAnchorProps } from '@elastic/eui';
+import { KibanaContext, IKibanaContext } from '../../index';
import { letBrowserHandleEvent } from './link_events';
/**
@@ -24,6 +25,10 @@ interface IEuiReactRouterProps {
export const EuiReactRouterHelper: React.FC = ({ to, onClick, children }) => {
const history = useHistory();
+ const { navigateToUrl } = useContext(KibanaContext) as IKibanaContext;
+
+ // Generate the correct link href (with basename etc. accounted for)
+ const href = history.createHref({ pathname: to });
const reactRouterLinkClick = (event: React.MouseEvent) => {
if (onClick) onClick(); // Run any passed click events (e.g. telemetry)
@@ -32,13 +37,10 @@ export const EuiReactRouterHelper: React.FC = ({ to, onCli
// Prevent regular link behavior, which causes a browser refresh.
event.preventDefault();
- // Push the route to the history.
- history.push(to);
+ // Perform SPA navigation.
+ navigateToUrl(href);
};
- // Generate the correct link href (with basename etc. accounted for)
- const href = history.createHref({ pathname: to });
-
const reactRouterProps = { href, onClick: reactRouterLinkClick };
return React.cloneElement(children as React.ReactElement, reactRouterProps);
};
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
index ca0d395c0d673..4aa171a5a5762 100644
--- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx
@@ -33,7 +33,6 @@ export const WorkplaceSearch: React.FC = () => {
- {/* Kibana displays a blank page on redirect if this isn't included */}
);