Explore: Turn ExplorePage.test into unit test (#72022)

* Extract logic from ExplorePage to a hook, add a test for the hook; remove ExplorePage test

* Remove extracted stuff from ExplorePage

* Clean up

* Fix minWidth logic
This commit is contained in:
Haris Rozajac 2023-07-26 12:46:57 -06:00 committed by GitHub
parent c7598cc6fb
commit 982624cf51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 39 deletions

View File

@ -1,24 +1,24 @@
import { css } from '@emotion/css';
import { inRange } from 'lodash';
import React, { useEffect, useState } from 'react';
import { useWindowSize } from 'react-use';
import React, { useEffect } from 'react';
import { ErrorBoundaryAlert } from '@grafana/ui';
import { SplitPaneWrapper } from 'app/core/components/SplitPaneWrapper/SplitPaneWrapper';
import { useGrafana } from 'app/core/context/GrafanaContext';
import { useNavModel } from 'app/core/hooks/useNavModel';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { useDispatch, useSelector } from 'app/types';
import { useSelector } from 'app/types';
import { ExploreQueryParams } from 'app/types/explore';
import { ExploreActions } from './ExploreActions';
import { ExplorePaneContainer } from './ExplorePaneContainer';
import { useExplorePageTitle } from './hooks/useExplorePageTitle';
import { useSplitSizeUpdater } from './hooks/useSplitSizeUpdater';
import { useStateSync } from './hooks/useStateSync';
import { useTimeSrvFix } from './hooks/useTimeSrvFix';
import { splitSizeUpdateAction } from './state/main';
import { isSplit, selectPanesEntries } from './state/selectors';
const MIN_PANE_WIDTH = 200;
const styles = {
pageScrollbarWrapper: css`
width: 100%;
@ -38,13 +38,9 @@ export default function ExplorePage(props: GrafanaRouteComponentProps<{}, Explor
// if we were to update the URL on state change, the title would not match the URL.
// Ultimately the URL is the single source of truth from which state is derived, the page title is not different
useExplorePageTitle(props.queryParams);
const dispatch = useDispatch();
const { keybindings, chrome } = useGrafana();
const navModel = useNavModel('explore');
const [rightPaneWidthRatio, setRightPaneWidthRatio] = useState(0.5);
const { width: windowWidth } = useWindowSize();
const minWidth = 200;
const exploreState = useSelector((state) => state.explore);
const { updateSplitSize, widthCalc } = useSplitSizeUpdater(MIN_PANE_WIDTH);
const panes = useSelector(selectPanesEntries);
const hasSplit = useSelector(isSplit);
@ -59,33 +55,6 @@ export default function ExplorePage(props: GrafanaRouteComponentProps<{}, Explor
keybindings.setupTimeRangeBindings(false);
}, [keybindings]);
const updateSplitSize = (size: number) => {
const evenSplitWidth = windowWidth / 2;
const areBothSimilar = inRange(size, evenSplitWidth - 100, evenSplitWidth + 100);
if (areBothSimilar) {
dispatch(splitSizeUpdateAction({ largerExploreId: undefined }));
} else {
dispatch(
splitSizeUpdateAction({
largerExploreId: size > evenSplitWidth ? panes[1][0] : panes[0][0],
})
);
}
setRightPaneWidthRatio(size / windowWidth);
};
let widthCalc = 0;
if (hasSplit) {
if (!exploreState.evenSplitPanes && exploreState.maxedExploreId) {
widthCalc = exploreState.maxedExploreId === panes[1][0] ? windowWidth - minWidth : minWidth;
} else if (exploreState.evenSplitPanes) {
widthCalc = Math.floor(windowWidth / 2);
} else if (rightPaneWidthRatio !== undefined) {
widthCalc = windowWidth * rightPaneWidthRatio;
}
}
return (
<div className={styles.pageScrollbarWrapper}>
<ExploreActions />
@ -93,8 +62,8 @@ export default function ExplorePage(props: GrafanaRouteComponentProps<{}, Explor
<SplitPaneWrapper
splitOrientation="vertical"
paneSize={widthCalc}
minSize={minWidth}
maxSize={minWidth * -1}
minSize={MIN_PANE_WIDTH}
maxSize={MIN_PANE_WIDTH * -1}
primary="second"
splitVisible={hasSplit}
paneStyle={{ overflow: 'auto', display: 'flex', flexDirection: 'column' }}

View File

@ -0,0 +1,57 @@
import { renderHook, act } from '@testing-library/react-hooks';
import React, { ReactNode } from 'react';
import { TestProvider } from 'test/helpers/TestProvider';
import { initialExploreState } from 'app/features/explore/state/main';
import { makeExplorePaneState } from 'app/features/explore/state/utils';
import { configureStore } from 'app/store/configureStore';
import { splitSizeUpdateAction } from '../state/main';
import { useSplitSizeUpdater } from './useSplitSizeUpdater';
describe('useSplitSizeUpdater', () => {
it('dispatches correct action and calculates widthCalc correctly', () => {
const store = configureStore({
explore: {
...initialExploreState,
panes: {
left: makeExplorePaneState(),
right: makeExplorePaneState(),
},
},
});
const minWidth = 200;
const dispatchMock = jest.fn().mockImplementation(store.dispatch);
const { result } = renderHook(() => useSplitSizeUpdater(minWidth), {
wrapper: ({ children }: { children: ReactNode }) => (
<TestProvider store={{ ...store, dispatch: dispatchMock }}>{children}</TestProvider>
),
});
// 1. Panes have similar width
act(() => {
result.current.updateSplitSize(450);
expect(dispatchMock).toHaveBeenCalledWith(splitSizeUpdateAction({ largerExploreId: undefined }));
expect(result.current.widthCalc).toBe(512);
});
// 2. Left pane is larger
act(() => {
result.current.updateSplitSize(300);
});
expect(dispatchMock).toHaveBeenCalledWith(splitSizeUpdateAction({ largerExploreId: 'left' }));
expect(result.current.widthCalc).toBe(300);
// 3. Right pane is larger
act(() => {
result.current.updateSplitSize(700);
});
expect(dispatchMock).toHaveBeenCalledWith(splitSizeUpdateAction({ largerExploreId: 'right' }));
expect(result.current.widthCalc).toBe(700);
});
});

View File

@ -0,0 +1,47 @@
import { inRange } from 'lodash';
import { useState } from 'react';
import { useWindowSize } from 'react-use';
import { useDispatch, useSelector } from 'app/types';
import { splitSizeUpdateAction } from '../state/main';
import { isSplit, selectPanesEntries } from '../state/selectors';
export const useSplitSizeUpdater = (minWidth: number) => {
const dispatch = useDispatch();
const { width: windowWidth } = useWindowSize();
const panes = useSelector(selectPanesEntries);
const hasSplit = useSelector(isSplit);
const [rightPaneWidthRatio, setRightPaneWidthRatio] = useState(0.5);
const exploreState = useSelector((state) => state.explore);
const updateSplitSize = (size: number) => {
const evenSplitWidth = windowWidth / 2;
const areBothSimilar = inRange(size, evenSplitWidth - 100, evenSplitWidth + 100);
if (areBothSimilar) {
dispatch(splitSizeUpdateAction({ largerExploreId: undefined }));
} else {
dispatch(
splitSizeUpdateAction({
largerExploreId: size > evenSplitWidth ? panes[1][0] : panes[0][0],
})
);
}
setRightPaneWidthRatio(size / windowWidth);
};
let widthCalc = 0;
if (hasSplit) {
if (!exploreState.evenSplitPanes && exploreState.maxedExploreId) {
widthCalc = exploreState.maxedExploreId === panes[1][0] ? windowWidth - minWidth : minWidth;
} else if (exploreState.evenSplitPanes) {
widthCalc = Math.floor(windowWidth / 2);
} else if (rightPaneWidthRatio !== undefined) {
widthCalc = windowWidth * rightPaneWidthRatio;
}
}
return { updateSplitSize, widthCalc };
};