Skip to content

Commit 57d76ed

Browse files
author
Constance
authored
[Enterprise Search] DRY out createHref helper for navigateToUrl calls (#78717) (#78800)
* DRY out createHref helper - that navigateToUrl will shortly also use + fix mockHistory type complaint * KibanaLogic: Update navigateToUrl to use createHref helper + add param.history value, since we're technically supposed to be using Kibana's passed history over anything from useHistory * Update breadcrumbs & eui link helpers w/ new KibanaLogic changes - navigateToUrl is now double-dipping createHref, so we update it to not do so - remove useHistory in favor of grabbing history from KibanaLogic * [Optional?] Update FlashMessages to grab history from KibanaLogic - since we're now storing it there, we might as well grab it as well instead of passing in props? * [Misc] Fix failing tests due to react router mock
1 parent 9aee232 commit 57d76ed

15 files changed

Lines changed: 122 additions & 39 deletions

File tree

x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7+
import { mockHistory } from './';
8+
79
export const mockKibanaValues = {
810
config: { host: 'http://localhost:3002' },
11+
history: mockHistory,
912
navigateToUrl: jest.fn(),
1013
setBreadcrumbs: jest.fn(),
1114
setDocTitle: jest.fn(),

x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router_history.mock.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const mockHistory = {
1515
pathname: '/current-path',
1616
},
1717
listen: jest.fn(() => jest.fn()),
18-
};
18+
} as any;
1919
export const mockLocation = {
2020
key: 'someKey',
2121
pathname: '/current-path',
@@ -25,6 +25,7 @@ export const mockLocation = {
2525
};
2626

2727
jest.mock('react-router-dom', () => ({
28+
...(jest.requireActual('react-router-dom') as object),
2829
useHistory: jest.fn(() => mockHistory),
2930
useLocation: jest.fn(() => mockLocation),
3031
}));

x-pack/plugins/enterprise_search/public/applications/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const renderApp = (
4141

4242
const unmountKibanaLogic = mountKibanaLogic({
4343
config,
44+
history: params.history,
4445
navigateToUrl: core.application.navigateToUrl,
4546
setBreadcrumbs: core.chrome.setBreadcrumbs,
4647
setDocTitle: core.chrome.docTitle.change,
@@ -53,9 +54,7 @@ export const renderApp = (
5354
errorConnecting,
5455
readOnlyMode: initialData.readOnlyMode,
5556
});
56-
const unmountFlashMessagesLogic = mountFlashMessagesLogic({
57-
history: params.history,
58-
});
57+
const unmountFlashMessagesLogic = mountFlashMessagesLogic();
5958

6059
ReactDOM.render(
6160
<I18nProvider>

x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
import { resetContext } from 'kea';
88

99
import { mockHistory } from '../../__mocks__';
10+
jest.mock('../kibana', () => ({
11+
KibanaLogic: { values: { history: mockHistory } },
12+
}));
1013

1114
import { FlashMessagesLogic, mountFlashMessagesLogic, IFlashMessage } from './';
1215

1316
describe('FlashMessagesLogic', () => {
14-
const mount = () => mountFlashMessagesLogic({ history: mockHistory as any });
17+
const mount = () => mountFlashMessagesLogic();
1518

1619
beforeEach(() => {
1720
jest.clearAllMocks();

x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import { kea, MakeLogicType } from 'kea';
88
import { ReactNode } from 'react';
9-
import { History } from 'history';
9+
10+
import { KibanaLogic } from '../kibana';
1011

1112
export interface IFlashMessage {
1213
type: 'success' | 'info' | 'warning' | 'error';
@@ -61,10 +62,10 @@ export const FlashMessagesLogic = kea<MakeLogicType<IFlashMessagesValues, IFlash
6162
},
6263
],
6364
},
64-
events: ({ props, values, actions }) => ({
65+
events: ({ values, actions }) => ({
6566
afterMount: () => {
6667
// On React Router navigation, clear previous flash messages and load any queued messages
67-
const unlisten = props.history.listen(() => {
68+
const unlisten = KibanaLogic.values.history.listen(() => {
6869
actions.clearFlashMessages();
6970
actions.setFlashMessages(values.queuedMessages);
7071
actions.clearQueuedMessages();
@@ -81,11 +82,7 @@ export const FlashMessagesLogic = kea<MakeLogicType<IFlashMessagesValues, IFlash
8182
/**
8283
* Mount/props helper
8384
*/
84-
interface IFlashMessagesLogicProps {
85-
history: History;
86-
}
87-
export const mountFlashMessagesLogic = (props: IFlashMessagesLogicProps) => {
88-
FlashMessagesLogic(props);
85+
export const mountFlashMessagesLogic = () => {
8986
const unmount = FlashMessagesLogic.mount();
9087
return unmount;
9188
};

x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66

77
import { mockHistory } from '../../__mocks__';
8+
jest.mock('../kibana', () => ({
9+
KibanaLogic: { values: { history: mockHistory } },
10+
}));
811

912
import {
1013
FlashMessagesLogic,
@@ -18,7 +21,7 @@ describe('Flash Message Helpers', () => {
1821
const message = 'I am a message';
1922

2023
beforeEach(() => {
21-
mountFlashMessagesLogic({ history: mockHistory as any });
24+
mountFlashMessagesLogic();
2225
});
2326

2427
it('setSuccessMessage()', () => {

x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ describe('KibanaLogic', () => {
2020
it('sets values from props', () => {
2121
mountKibanaLogic(mockKibanaValues);
2222

23-
expect(KibanaLogic.values).toEqual(mockKibanaValues);
23+
expect(KibanaLogic.values).toEqual({
24+
...mockKibanaValues,
25+
navigateToUrl: expect.any(Function),
26+
});
2427
});
2528

2629
it('gracefully handles missing configs', () => {
@@ -29,4 +32,20 @@ describe('KibanaLogic', () => {
2932
expect(KibanaLogic.values.config).toEqual({});
3033
});
3134
});
35+
36+
describe('navigateToUrl()', () => {
37+
beforeEach(() => mountKibanaLogic(mockKibanaValues));
38+
39+
it('runs paths through createHref before calling navigateToUrl', () => {
40+
KibanaLogic.values.navigateToUrl('/test');
41+
42+
expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/app/enterprise_search/test');
43+
});
44+
45+
it('does not run paths through createHref if the shouldNotCreateHref option is passed', () => {
46+
KibanaLogic.values.navigateToUrl('/test', { shouldNotCreateHref: true });
47+
48+
expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/test');
49+
});
50+
});
3251
});

x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,40 @@
66

77
import { kea, MakeLogicType } from 'kea';
88

9+
import { History } from 'history';
910
import { ApplicationStart, ChromeBreadcrumb } from 'src/core/public';
1011

11-
export interface IKibanaValues {
12+
import { createHref, ICreateHrefOptions } from '../react_router_helpers';
13+
14+
interface IKibanaLogicProps {
1215
config: { host?: string };
16+
history: History;
1317
navigateToUrl: ApplicationStart['navigateToUrl'];
1418
setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void;
1519
setDocTitle(title: string): void;
1620
}
21+
export interface IKibanaValues extends IKibanaLogicProps {
22+
navigateToUrl(path: string, options?: ICreateHrefOptions): Promise<void>;
23+
}
1724

1825
export const KibanaLogic = kea<MakeLogicType<IKibanaValues>>({
1926
path: ['enterprise_search', 'kibana_logic'],
2027
reducers: ({ props }) => ({
2128
config: [props.config || {}, {}],
22-
navigateToUrl: [props.navigateToUrl, {}],
29+
history: [props.history, {}],
30+
navigateToUrl: [
31+
(url: string, options?: ICreateHrefOptions) => {
32+
const href = createHref(url, props.history, options);
33+
return props.navigateToUrl(href);
34+
},
35+
{},
36+
],
2337
setBreadcrumbs: [props.setBreadcrumbs, {}],
2438
setDocTitle: [props.setDocTitle, {}],
2539
}),
2640
});
2741

28-
export const mountKibanaLogic = (props: IKibanaValues) => {
42+
export const mountKibanaLogic = (props: IKibanaLogicProps) => {
2943
KibanaLogic(props);
3044
const unmount = KibanaLogic.mount();
3145
return unmount;

x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
*/
66

77
import '../../__mocks__/kea.mock';
8-
import '../../__mocks__/react_router_history.mock';
98
import { mockKibanaValues, mockHistory } from '../../__mocks__';
109

11-
jest.mock('../react_router_helpers', () => ({ letBrowserHandleEvent: jest.fn(() => false) }));
10+
jest.mock('../react_router_helpers', () => ({
11+
letBrowserHandleEvent: jest.fn(() => false),
12+
createHref: jest.requireActual('../react_router_helpers').createHref,
13+
}));
1214
import { letBrowserHandleEvent } from '../react_router_helpers';
1315

1416
import {
@@ -50,21 +52,23 @@ describe('useBreadcrumbs', () => {
5052

5153
it('prevents default navigation and uses React Router history on click', () => {
5254
const breadcrumb = useBreadcrumbs([{ text: '', path: '/test' }])[0] as any;
55+
56+
expect(breadcrumb.href).toEqual('/app/enterprise_search/test');
57+
expect(mockHistory.createHref).toHaveBeenCalled();
58+
5359
const event = { preventDefault: jest.fn() };
5460
breadcrumb.onClick(event);
5561

56-
expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/app/enterprise_search/test');
57-
expect(mockHistory.createHref).toHaveBeenCalled();
5862
expect(event.preventDefault).toHaveBeenCalled();
63+
expect(mockKibanaValues.navigateToUrl).toHaveBeenCalled();
5964
});
6065

6166
it('does not call createHref if shouldNotCreateHref is passed', () => {
6267
const breadcrumb = useBreadcrumbs([
6368
{ text: '', path: '/test', shouldNotCreateHref: true },
6469
])[0] as any;
65-
breadcrumb.onClick({ preventDefault: () => null });
6670

67-
expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/test');
71+
expect(breadcrumb.href).toEqual('/test');
6872
expect(mockHistory.createHref).not.toHaveBeenCalled();
6973
});
7074

x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66

77
import { useValues } from 'kea';
8-
import { useHistory } from 'react-router-dom';
98
import { EuiBreadcrumb } from '@elastic/eui';
109

1110
import { KibanaLogic } from '../../shared/kibana';
@@ -16,7 +15,7 @@ import {
1615
WORKPLACE_SEARCH_PLUGIN,
1716
} from '../../../../common/constants';
1817

19-
import { letBrowserHandleEvent } from '../react_router_helpers';
18+
import { letBrowserHandleEvent, createHref } from '../react_router_helpers';
2019

2120
/**
2221
* Generate React-Router-friendly EUI breadcrumb objects
@@ -33,20 +32,17 @@ interface IBreadcrumb {
3332
export type TBreadcrumbs = IBreadcrumb[];
3433

3534
export const useBreadcrumbs = (breadcrumbs: TBreadcrumbs) => {
36-
const history = useHistory();
37-
const { navigateToUrl } = useValues(KibanaLogic);
35+
const { navigateToUrl, history } = useValues(KibanaLogic);
3836

3937
return breadcrumbs.map(({ text, path, shouldNotCreateHref }) => {
4038
const breadcrumb = { text } as EuiBreadcrumb;
4139

4240
if (path) {
43-
const href = shouldNotCreateHref ? path : (history.createHref({ pathname: path }) as string);
44-
45-
breadcrumb.href = href;
41+
breadcrumb.href = createHref(path, history, { shouldNotCreateHref });
4642
breadcrumb.onClick = (event) => {
4743
if (letBrowserHandleEvent(event)) return;
4844
event.preventDefault();
49-
navigateToUrl(href);
45+
navigateToUrl(path, { shouldNotCreateHref });
5046
};
5147
}
5248

0 commit comments

Comments
 (0)