[Fleet] useHistoryBlock should preserve url search on confirm (#136133)

This commit is contained in:
Nicolas Chaulet 2022-07-11 15:37:17 -04:00 committed by GitHub
parent 7dbc1c6822
commit 24e76db956
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 113 additions and 3 deletions

View file

@ -0,0 +1,105 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { act } from '@testing-library/react-hooks';
import { createFleetTestRendererMock } from '../../../../../../mock';
import { useHistoryBlock } from '.';
describe('useHistoryBlock', () => {
describe('without search params', () => {
it('should not block if not edited', () => {
const renderer = createFleetTestRendererMock();
renderer.renderHook(() => useHistoryBlock(false));
act(() => renderer.mountHistory.push('/test'));
const { location } = renderer.mountHistory;
expect(location.pathname).toBe('/test');
expect(location.search).toBe('');
expect(renderer.startServices.overlays.openConfirm).not.toBeCalled();
});
it('should block if edited', async () => {
const renderer = createFleetTestRendererMock();
renderer.startServices.overlays.openConfirm.mockResolvedValue(true);
renderer.renderHook(() => useHistoryBlock(true));
act(() => renderer.mountHistory.push('/test'));
// needed because we have an async useEffect
await act(() => new Promise((resolve) => resolve()));
expect(renderer.startServices.overlays.openConfirm).toBeCalled();
expect(renderer.startServices.application.navigateToUrl).toBeCalledWith(
'/mock/test',
expect.anything()
);
});
it('should block if edited and not navigate on cancel', async () => {
const renderer = createFleetTestRendererMock();
renderer.startServices.overlays.openConfirm.mockResolvedValue(false);
renderer.renderHook(() => useHistoryBlock(true));
act(() => renderer.mountHistory.push('/test'));
// needed because we have an async useEffect
await act(() => new Promise((resolve) => resolve()));
expect(renderer.startServices.overlays.openConfirm).toBeCalled();
expect(renderer.startServices.application.navigateToUrl).not.toBeCalled();
});
});
describe('with search params', () => {
it('should not block if not edited', () => {
const renderer = createFleetTestRendererMock();
renderer.renderHook(() => useHistoryBlock(false));
act(() => renderer.mountHistory.push('/test?param=test'));
const { location } = renderer.mountHistory;
expect(location.pathname).toBe('/test');
expect(location.search).toBe('?param=test');
expect(renderer.startServices.overlays.openConfirm).not.toBeCalled();
});
it('should block if edited and navigate on confirm', async () => {
const renderer = createFleetTestRendererMock();
renderer.startServices.overlays.openConfirm.mockResolvedValue(true);
renderer.renderHook(() => useHistoryBlock(true));
act(() => renderer.mountHistory.push('/test?param=test'));
// needed because we have an async useEffect
await act(() => new Promise((resolve) => resolve()));
expect(renderer.startServices.overlays.openConfirm).toBeCalled();
expect(renderer.startServices.application.navigateToUrl).toBeCalledWith(
'/mock/test?param=test',
expect.anything()
);
});
it('should block if edited and not navigate on cancel', async () => {
const renderer = createFleetTestRendererMock();
renderer.startServices.overlays.openConfirm.mockResolvedValue(false);
renderer.renderHook(() => useHistoryBlock(true));
act(() => renderer.mountHistory.push('/test?param=test'));
// needed because we have an async useEffect
await act(() => new Promise((resolve) => resolve()));
expect(renderer.startServices.overlays.openConfirm).toBeCalled();
expect(renderer.startServices.application.navigateToUrl).not.toBeCalled();
});
});
});

View file

@ -35,7 +35,7 @@ export function useHistoryBlock(isEdited: boolean) {
if (confirmRes) {
unblock();
application.navigateToUrl(state.pathname, { state: state.state });
application.navigateToUrl(state.pathname + state.search, { state: state.state });
}
}
confirmAsync();

View file

@ -12,6 +12,7 @@ import type { RenderOptions, RenderResult } from '@testing-library/react';
import { render as reactRender, act } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import type { RenderHookResult } from '@testing-library/react-hooks';
import { Router } from 'react-router-dom';
import { themeServiceMock } from '@kbn/core/public/mocks';
@ -27,6 +28,7 @@ import { createConfigurationMock } from './plugin_configuration';
import { createStartMock } from './plugin_interfaces';
import { createStartServices } from './fleet_start_services';
import type { MockedFleetStart, MockedFleetStartServices } from './types';
type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResult;
/**
@ -58,18 +60,21 @@ export const createFleetTestRendererMock = (): TestRenderer => {
const extensions: UIExtensionsStorage = {};
const startServices = createStartServices(basePath);
const history = createMemoryHistory({ initialEntries: [basePath] });
const mountHistory = new ScopedHistory(history, basePath);
const HookWrapper = memo(({ children }) => {
return (
<startServices.i18n.Context>
<KibanaContextProvider services={{ ...startServices }}>{children}</KibanaContextProvider>
<Router history={mountHistory}>
<KibanaContextProvider services={{ ...startServices }}>{children}</KibanaContextProvider>
</Router>
</startServices.i18n.Context>
);
});
const testRendererMocks: TestRenderer = {
history,
mountHistory: new ScopedHistory(history, basePath),
mountHistory,
startServices,
config: createConfigurationMock(),
startInterface: createStartMock(extensions),