Skip to content

Commit

Permalink
[Security Solution] Update use_url_state to work with new side nav (e…
Browse files Browse the repository at this point in the history
…lastic#132518)

* Fix landing pages browser tab title

* Fix new navigation url state

* Fix unit tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
machadoum and kibanamachine authored May 23, 2022
1 parent 693b3e8 commit b59fb97
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import { UrlStateContainerPropTypes } from './types';
import { useUrlStateHooks } from './use_url_state';
import { waitFor } from '@testing-library/react';
import { useLocation } from 'react-router-dom';
import { updateAppLinks } from '../../links';
import { getAppLinks } from '../../links/app_links';
import { StartPlugins } from '../../../types';
import { allowedExperimentalValues } from '../../../../common/experimental_features';
import { coreMock } from '@kbn/core/public/mocks';

let mockProps: UrlStateContainerPropTypes;

Expand Down Expand Up @@ -78,10 +83,36 @@ jest.mock('react-router-dom', () => {
};
});

const mockedUseIsGroupedNavigationEnabled = jest.fn();
jest.mock('../navigation/helpers', () => ({
useIsGroupedNavigationEnabled: () => mockedUseIsGroupedNavigationEnabled(),
}));

describe('UrlStateContainer', () => {
beforeAll(async () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(false);

const appLinks = await getAppLinks(coreMock.createStart(), {} as StartPlugins);
updateAppLinks(appLinks, {
experimentalFeatures: allowedExperimentalValues,
capabilities: {
navLinks: {},
management: {},
catalogue: {},
actions: { show: true, crud: true },
siem: {
show: true,
crud: true,
},
},
});
});

afterEach(() => {
jest.clearAllMocks();
mockedUseIsGroupedNavigationEnabled.mockReturnValue(false);
});

describe('handleInitialize', () => {
describe('URL state updates redux', () => {
describe('relative timerange actions are called with correct data on component mount', () => {
Expand Down Expand Up @@ -226,6 +257,44 @@ describe('UrlStateContainer', () => {
expect(mockHistory.replace).not.toHaveBeenCalled();
});

it("it doesn't update URL state when on admin page and grouped nav disabled", () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(false);
mockProps = getMockPropsObj({
page: CONSTANTS.unknown,
examplePath: '/administration',
namespaceLower: 'administration',
pageName: SecurityPageName.administration,
detailName: undefined,
}).noSearch.undefinedQuery;

(useLocation as jest.Mock).mockReturnValue({
pathname: mockProps.pathName,
});

mount(<HookWrapper hookProps={mockProps} hook={(args) => useUrlStateHooks(args)} />);

expect(mockHistory.replace.mock.calls[0][0].search).toBe('?');
});

it("it doesn't update URL state when on admin page and grouped nav enabled", () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(true);
mockProps = getMockPropsObj({
page: CONSTANTS.unknown,
examplePath: '/dashboards',
namespaceLower: 'dashboards',
pageName: SecurityPageName.dashboardsLanding,
detailName: undefined,
}).noSearch.undefinedQuery;

(useLocation as jest.Mock).mockReturnValue({
pathname: mockProps.pathName,
});

mount(<HookWrapper hookProps={mockProps} hook={(args) => useUrlStateHooks(args)} />);

expect(mockHistory.replace.mock.calls[0][0].search).toBe('?');
});

it('it removes empty AppQuery state from URL', () => {
mockProps = {
...getMockProps(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { getFilterQuery, getMockPropsObj, mockHistory, testCases } from './test_
import { UrlStateContainerPropTypes } from './types';
import { useUrlStateHooks } from './use_url_state';
import { useLocation } from 'react-router-dom';
import { MANAGEMENT_PATH } from '../../../../common/constants';
import { DASHBOARDS_PATH, MANAGEMENT_PATH } from '../../../../common/constants';
import { getAppLinks } from '../../links/app_links';
import { StartPlugins } from '../../../types';
import { updateAppLinks } from '../../links';
import { allowedExperimentalValues } from '../../../../common/experimental_features';
import { coreMock } from '@kbn/core/public/mocks';

let mockProps: UrlStateContainerPropTypes;

Expand Down Expand Up @@ -45,7 +50,31 @@ jest.mock('react-redux', () => {
};
});

const mockedUseIsGroupedNavigationEnabled = jest.fn();
jest.mock('../navigation/helpers', () => ({
useIsGroupedNavigationEnabled: () => mockedUseIsGroupedNavigationEnabled(),
}));

describe('UrlStateContainer - lodash.throttle mocked to test update url', () => {
beforeAll(async () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(false);

const appLinks = await getAppLinks(coreMock.createStart(), {} as StartPlugins);
updateAppLinks(appLinks, {
experimentalFeatures: allowedExperimentalValues,
capabilities: {
navLinks: {},
management: {},
catalogue: {},
actions: { show: true, crud: true },
siem: {
show: true,
crud: true,
},
},
});
});

afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
Expand Down Expand Up @@ -210,7 +239,8 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
});
});

test("administration page doesn't has query string", () => {
test("administration page doesn't has query string when grouped nav disabled", () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(false);
mockProps = getMockPropsObj({
page: CONSTANTS.networkPage,
examplePath: '/network',
Expand Down Expand Up @@ -285,6 +315,83 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () =>
state: '',
});
});

test("dashboards page doesn't has query string when grouped nav enabled", () => {
mockedUseIsGroupedNavigationEnabled.mockReturnValue(true);
mockProps = getMockPropsObj({
page: CONSTANTS.networkPage,
examplePath: '/network',
namespaceLower: 'network',
pageName: SecurityPageName.network,
detailName: undefined,
}).noSearch.definedQuery;

const urlState = {
...mockProps.urlState,
[CONSTANTS.appQuery]: getFilterQuery(),
[CONSTANTS.timerange]: {
global: {
[CONSTANTS.timerange]: {
from: '2020-07-07T08:20:18.966Z',
fromStr: 'now-24h',
kind: 'relative',
to: '2020-07-08T08:20:18.966Z',
toStr: 'now',
},
linkTo: ['timeline'],
},
timeline: {
[CONSTANTS.timerange]: {
from: '2020-07-07T08:20:18.966Z',
fromStr: 'now-24h',
kind: 'relative',
to: '2020-07-08T08:20:18.966Z',
toStr: 'now',
},
linkTo: ['global'],
},
},
};

const updatedMockProps = {
...getMockPropsObj({
...mockProps,
page: CONSTANTS.unknown,
examplePath: DASHBOARDS_PATH,
namespaceLower: 'dashboards',
pageName: SecurityPageName.dashboardsLanding,
detailName: undefined,
}).noSearch.definedQuery,
urlState,
};

(useLocation as jest.Mock).mockReturnValue({
pathname: mockProps.pathName,
});

const wrapper = mount(
<HookWrapper
hookProps={{ ...mockProps, urlState }}
hook={(args) => useUrlStateHooks(args)}
/>
);

(useLocation as jest.Mock).mockReturnValue({
pathname: updatedMockProps.pathName,
});

wrapper.setProps({
hookProps: updatedMockProps,
});

wrapper.update();
expect(mockHistory.replace.mock.calls[1][0]).toStrictEqual({
hash: '',
pathname: DASHBOARDS_PATH,
search: '?',
state: '',
});
});
});

describe('handleInitialize', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ import {
import { TimelineUrl } from '../../../timelines/store/timeline/model';
import { UrlInputsModel } from '../../store/inputs/model';
import { queryTimelineByIdOnUrlChange } from './query_timeline_by_id_on_url_change';
import { getLinkInfo } from '../../links';
import { SecurityPageName } from '../../../app/types';
import { useIsGroupedNavigationEnabled } from '../navigation/helpers';

function usePrevious(value: PreviousLocationUrlState) {
const ref = useRef<PreviousLocationUrlState>(value);
Expand All @@ -62,17 +65,20 @@ export const useUrlStateHooks = ({
const { filterManager, savedQueries } = useKibana().services.data.query;
const { pathname: browserPathName } = useLocation();
const prevProps = usePrevious({ pathName, pageName, urlState, search });
const isGroupedNavEnabled = useIsGroupedNavigationEnabled();

const linkInfo = pageName ? getLinkInfo(pageName as SecurityPageName) : undefined;
const { setInitialStateFromUrl, updateTimeline, updateTimelineIsLoading } =
useSetInitialStateFromUrl();

const handleInitialize = useCallback(
(type: UrlStateType) => {
const urlStateUpdatesToStore: UrlStateToRedux[] = [];
const urlStateUpdatesToLocation: ReplaceStateInLocation[] = [];
const skipUrlState = isGroupedNavEnabled ? linkInfo?.skipUrlState : isAdministration(type);

// Delete all query strings from URL when the page is security/administration (Manage menu group)
if (isAdministration(type)) {
if (skipUrlState) {
ALL_URL_STATE_KEYS.forEach((urlKey: KeyUrlState) => {
urlStateUpdatesToLocation.push({
urlStateToReplace: '',
Expand Down Expand Up @@ -146,6 +152,8 @@ export const useUrlStateHooks = ({
setInitialStateFromUrl,
urlState,
isFirstPageLoad,
isGroupedNavEnabled,
linkInfo?.skipUrlState,
]
);

Expand All @@ -159,8 +167,9 @@ export const useUrlStateHooks = ({
if (browserPathName !== pathName) return;

const type: UrlStateType = getUrlType(pageName);
const skipUrlState = isGroupedNavEnabled ? linkInfo?.skipUrlState : isAdministration(type);

if (!deepEqual(urlState, prevProps.urlState) && !isFirstPageLoad && !isAdministration(type)) {
if (!deepEqual(urlState, prevProps.urlState) && !isFirstPageLoad && !skipUrlState) {
const urlStateUpdatesToLocation: ReplaceStateInLocation[] = ALL_URL_STATE_KEYS.map(
(urlKey: KeyUrlState) => ({
urlStateToReplace: getUrlStateKeyValue(urlState, urlKey),
Expand All @@ -186,11 +195,17 @@ export const useUrlStateHooks = ({
browserPathName,
handleInitialize,
search,
isGroupedNavEnabled,
linkInfo?.skipUrlState,
]);

useEffect(() => {
document.title = `${getTitle(pageName, navTabs)} - Kibana`;
}, [pageName, navTabs]);
if (!isGroupedNavEnabled) {
document.title = `${getTitle(pageName, navTabs)} - Kibana`;
} else {
document.title = `${linkInfo?.title ?? ''} - Kibana`;
}
}, [pageName, navTabs, isGroupedNavEnabled, linkInfo]);

useEffect(() => {
queryTimelineByIdOnUrlChange({
Expand Down

0 comments on commit b59fb97

Please sign in to comment.