[8.6] [ResponseOps][Cases] Back button navigation out of the cases view (#145358) (#145734)

# Backport

This will backport the following commits from `main` to `8.6`:
- [[ResponseOps][Cases] Back button navigation out of the cases view
(#145358)](https://github.com/elastic/kibana/pull/145358)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Antonio","email":"antonio.coelho@elastic.co"},"sourceCommit":{"committedDate":"2022-11-18T11:29:55Z","message":"[ResponseOps][Cases]
Back button navigation out of the cases view (#145358)\n\n##
Summary\r\n\r\nFixes #145110 \r\n\r\nBesides our changes in the
`useAllCasesQueryParams` I noticed that
the\r\n`DatePickerContextProvider` was causing a similar
issue.\r\n\r\nSome pages in Observability get the `dateFrom` and
`dateTo` URL\r\nparameters even if there is no date picker on the page.
The\r\n`DatePickerContextProvider` was adding these parameters were
being added\r\non mount with `history.push` which caused us to have to
click as many as\r\n3/4(!) times backspace to navigate out of a page we
just visited.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"4e26f09276aa595900b9ddfdea105ee0c5ddbd9e","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","Team:ResponseOps","Feature:Cases","backport:prev-minor","v8.6.0","v8.7.0"],"number":145358,"url":"https://github.com/elastic/kibana/pull/145358","mergeCommit":{"message":"[ResponseOps][Cases]
Back button navigation out of the cases view (#145358)\n\n##
Summary\r\n\r\nFixes #145110 \r\n\r\nBesides our changes in the
`useAllCasesQueryParams` I noticed that
the\r\n`DatePickerContextProvider` was causing a similar
issue.\r\n\r\nSome pages in Observability get the `dateFrom` and
`dateTo` URL\r\nparameters even if there is no date picker on the page.
The\r\n`DatePickerContextProvider` was adding these parameters were
being added\r\non mount with `history.push` which caused us to have to
click as many as\r\n3/4(!) times backspace to navigate out of a page we
just visited.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"4e26f09276aa595900b9ddfdea105ee0c5ddbd9e"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/145358","number":145358,"mergeCommit":{"message":"[ResponseOps][Cases]
Back button navigation out of the cases view (#145358)\n\n##
Summary\r\n\r\nFixes #145110 \r\n\r\nBesides our changes in the
`useAllCasesQueryParams` I noticed that
the\r\n`DatePickerContextProvider` was causing a similar
issue.\r\n\r\nSome pages in Observability get the `dateFrom` and
`dateTo` URL\r\nparameters even if there is no date picker on the page.
The\r\n`DatePickerContextProvider` was adding these parameters were
being added\r\non mount with `history.push` which caused us to have to
click as many as\r\n3/4(!) times backspace to navigate out of a page we
just visited.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"4e26f09276aa595900b9ddfdea105ee0c5ddbd9e"}}]}]
BACKPORT-->

Co-authored-by: Antonio <antonio.coelho@elastic.co>
This commit is contained in:
Kibana Machine 2022-11-18 10:27:01 -05:00 committed by GitHub
parent 68bd9a95e7
commit 31f3c3ea62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 18 deletions

View file

@ -7,7 +7,7 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import { renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react-hooks';
import { TestProviders } from '../../common/mock';
import {
@ -36,6 +36,7 @@ jest.mock('react-router-dom', () => ({
return mockLocation;
}),
useHistory: jest.fn().mockReturnValue({
replace: jest.fn(),
push: jest.fn(),
location: {
search: '',
@ -71,12 +72,12 @@ describe('useAllCasesQueryParams', () => {
});
});
it('calls history.push with default values on first run', () => {
it('calls history.replace with default values on first run', () => {
renderHook(() => useAllCasesQueryParams(), {
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});
expect(useHistory().push).toHaveBeenCalledWith({
expect(useHistory().replace).toHaveBeenCalledWith({
search: stringify(URL_DEFAULTS),
});
});
@ -109,11 +110,27 @@ describe('useAllCasesQueryParams', () => {
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});
expect(useHistory().push).toHaveBeenCalledWith({
expect(useHistory().replace).toHaveBeenCalledWith({
search: stringify(expectedUrl),
});
});
it('calls history.replace on first run and history.push onwards', () => {
const { result } = renderHook(() => useAllCasesQueryParams(), {
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});
expect(useHistory().replace).toHaveBeenCalled();
expect(useHistory().push).toHaveBeenCalledTimes(0);
act(() => {
result.current.setQueryParams({ perPage: DEFAULT_TABLE_LIMIT + 10 });
});
expect(useHistory().replace).toHaveBeenCalled();
expect(useHistory().push).toHaveBeenCalledTimes(1);
});
it('preserves other url parameters', () => {
const nonDefaultUrlParams = {
foo: 'bar',
@ -126,7 +143,7 @@ describe('useAllCasesQueryParams', () => {
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});
expect(useHistory().push).toHaveBeenCalledWith({
expect(useHistory().replace).toHaveBeenCalledWith({
search: stringify(expectedUrl),
});
});

View file

@ -93,10 +93,16 @@ export function useAllCasesQueryParams(isModalView: boolean = false) {
if (!isEqual(newUrlParams, urlParams)) {
try {
history.push({
const newHistory = {
...location,
search: stringify({ ...parsedUrlParams, ...newUrlParams }),
});
};
if (isFirstRenderRef.current) {
history.replace(newHistory);
} else {
history.push(newHistory);
}
} catch {
// silently fail
}

View file

@ -116,7 +116,8 @@ describe('DatePicker', () => {
});
// It updates the URL when it doesn't contain the range.
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryReplace).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledTimes(0);
wrapper.find(EuiSuperDatePicker).props().onTimeChange({
start: 'now-90m',
@ -124,7 +125,7 @@ describe('DatePicker', () => {
isInvalid: false,
isQuickSelection: true,
});
expect(mockHistoryPush).toHaveBeenCalledTimes(2);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenLastCalledWith(
expect.objectContaining({
search: 'rangeFrom=now-90m&rangeTo=now-60m',

View file

@ -37,19 +37,28 @@ export function DatePickerContextProvider({ children }: { children: React.ReactE
const history = useHistory();
const updateUrl = useCallback(
(nextQuery: {
rangeFrom?: string;
rangeTo?: string;
refreshPaused?: boolean;
refreshInterval?: number;
}) => {
history.push({
(
nextQuery: {
rangeFrom?: string;
rangeTo?: string;
refreshPaused?: boolean;
refreshInterval?: number;
},
isFirstRender: boolean = false
) => {
const newHistory = {
...location,
search: fromQuery({
...toQuery(location.search),
...nextQuery,
}),
});
};
if (isFirstRender) {
history.replace(newHistory);
} else {
history.push(newHistory);
}
},
[history, location]
);
@ -108,7 +117,7 @@ export function DatePickerContextProvider({ children }: { children: React.ReactE
);
useMount(() => {
updateUrl({ rangeFrom: relativeStart, rangeTo: relativeEnd });
updateUrl({ rangeFrom: relativeStart, rangeTo: relativeEnd }, true);
});
return (