Unverified Commit 961c07b9 authored by Manoj Pandian Sakthivel's avatar Manoj Pandian Sakthivel Committed by GitHub
Browse files

Close drawer view when modal changes (#503)

parent 51c4899d
Pipeline #159738 passed with stages
in 5 minutes and 46 seconds
......@@ -15,10 +15,19 @@
*/
import React from 'react';
import configureMockStore from 'redux-mock-store';
import { render } from '@testing-library/react';
import { getType } from 'typesafe-actions';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import userEvent from '@testing-library/user-event';
import set from 'lodash/fp/set';
import { TrackPanelBar, TrackPanelBarProps } from './TrackPanelBar';
import { TrackPanelBar } from './TrackPanelBar';
import * as drawerActions from '../../drawer/drawerActions';
import * as trackPanelActions from 'src/content/app/browser/track-panel/trackPanelActions';
import { DrawerView } from 'src/content/app/browser/drawer/drawerState';
jest.mock(
'src/shared/components/image-button/ImageButton',
......@@ -27,58 +36,160 @@ jest.mock(
)
);
const fakeGenomeId = 'human';
const mockState = {
drawer: {
isDrawerOpened: { [fakeGenomeId]: false },
drawerView: { [fakeGenomeId]: DrawerView.BOOKMARKS }
},
browser: {
browserEntity: {
activeGenomeId: fakeGenomeId
},
trackPanel: {
[fakeGenomeId]: {
isTrackPanelOpened: true,
trackPanelModalView: 'bookmarks'
}
}
}
};
const mockStore = configureMockStore([thunk]);
let store: ReturnType<typeof mockStore>;
const wrapInRedux = (state: typeof mockState = mockState) => {
store = mockStore(state);
return render(
<Provider store={store}>
<TrackPanelBar />
</Provider>
);
};
describe('<TrackPanelBar />', () => {
beforeEach(() => {
jest.resetAllMocks();
});
const defaultProps: TrackPanelBarProps = {
isTrackPanelModalOpened: true,
isTrackPanelOpened: true,
trackPanelModalView: 'foo',
closeTrackPanelModal: jest.fn(),
openTrackPanelModal: jest.fn(),
toggleTrackPanel: jest.fn()
};
describe('rendering', () => {
it('displays correct number of buttons', () => {
const { container } = render(<TrackPanelBar {...defaultProps} />);
const { container } = wrapInRedux();
expect(container.querySelectorAll('button').length).toBe(6);
});
it('passes correct data to callbacks when buttons are clicked', () => {
const { container } = render(<TrackPanelBar {...defaultProps} />);
const { container } = wrapInRedux(
set(
`browser.trackPanel.${fakeGenomeId}.trackPanelModalView`,
'',
mockState
)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
expect(defaultProps.openTrackPanelModal).toHaveBeenCalledWith(
'bookmarks'
);
const toggleTrackPanelAction = store
.getActions()
.find(
(action) =>
action.type === getType(trackPanelActions.updateTrackPanelForGenome)
);
const expectedPayload = {
activeGenomeId: fakeGenomeId,
data: {
...mockState.browser.trackPanel[fakeGenomeId],
trackPanelModalView: 'bookmarks',
isTrackPanelModalOpened: true
}
};
expect(toggleTrackPanelAction.payload).toEqual(expectedPayload);
});
it('opens the track panel if it is closed when a button is clicked', () => {
const props = { ...defaultProps, isTrackPanelOpened: false };
const { container } = render(<TrackPanelBar {...props} />);
const { container } = wrapInRedux(
set(
`browser.trackPanel.${fakeGenomeId}.isTrackPanelOpened`,
false,
mockState
)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
expect(defaultProps.toggleTrackPanel).toHaveBeenCalledWith(true);
const toggleTrackPanelAction = store
.getActions()
.find(
(action) =>
action.type === getType(trackPanelActions.updateTrackPanelForGenome)
);
const expectedPayload = {
activeGenomeId: fakeGenomeId,
data: {
...mockState.browser.trackPanel[fakeGenomeId],
isTrackPanelOpened: true
}
};
expect(toggleTrackPanelAction.payload).toEqual(expectedPayload);
});
it('causes track panel modal to close if a pressed button is clicked again', () => {
const props = { ...defaultProps, trackPanelModalView: 'bookmarks' }; // the modal is open and is showing bookmarks
const { container } = render(<TrackPanelBar {...props} />);
const { container } = wrapInRedux();
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
expect(defaultProps.closeTrackPanelModal).toHaveBeenCalled();
const toggleTrackPanelAction = store
.getActions()
.find(
(action) =>
action.type === getType(trackPanelActions.updateTrackPanelForGenome)
);
const expectedPayload = {
activeGenomeId: fakeGenomeId,
data: {
...mockState.browser.trackPanel[fakeGenomeId],
isTrackPanelModalOpened: false,
isTrackPanelOpened: true,
trackPanelModalView: ''
}
};
expect(toggleTrackPanelAction.payload).toEqual(expectedPayload);
});
it('closes drawer view when the modal view changes', () => {
const { container } = wrapInRedux(
set(`drawer.isDrawerOpened.${fakeGenomeId}`, true, mockState)
);
const bookmarksButton = [...container.querySelectorAll('button')].find(
(button) => button.innerHTML === 'Bookmarks'
) as HTMLButtonElement;
userEvent.click(bookmarksButton);
const drawerToggleAction = store
.getActions()
.find(
(action) =>
action.type === getType(drawerActions.toggleDrawerForGenome)
);
expect(drawerToggleAction.payload).toEqual({
[fakeGenomeId]: false
});
});
});
});
......@@ -15,10 +15,9 @@
*/
import React from 'react';
import { connect } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import {
getIsTrackPanelModalOpened,
getIsTrackPanelOpened,
getTrackPanelModalView
} from '../trackPanelSelectors';
......@@ -27,6 +26,8 @@ import {
closeTrackPanelModal,
openTrackPanelModal
} from '../trackPanelActions';
import { toggleDrawer } from 'src/content/app/browser/drawer/drawerActions';
import { getIsDrawerOpened } from 'src/content/app/browser/drawer/drawerSelectors';
import ImageButton from 'src/shared/components/image-button/ImageButton';
......@@ -37,36 +38,34 @@ import { ReactComponent as personalDataIcon } from 'static/img/sidebar/own-data.
import { ReactComponent as shareIcon } from 'static/img/sidebar/share.svg';
import { ReactComponent as downloadIcon } from 'static/img/sidebar/download.svg';
import { RootState } from 'src/store';
import { Status } from 'src/shared/types/status';
import styles from 'src/shared/components/layout/StandardAppLayout.scss';
export type TrackPanelBarProps = {
isTrackPanelModalOpened: boolean;
isTrackPanelOpened: boolean;
trackPanelModalView: string;
closeTrackPanelModal: () => void;
openTrackPanelModal: (trackPanelModalView: string) => void;
toggleTrackPanel: (isTrackPanelOpened?: boolean) => void;
};
export const TrackPanelBar = () => {
const isTrackPanelOpened = useSelector(getIsTrackPanelOpened);
const trackPanelModalView = useSelector(getTrackPanelModalView);
const isDrawerOpened = useSelector(getIsDrawerOpened);
const dispatch = useDispatch();
export const TrackPanelBar = (props: TrackPanelBarProps) => {
const toggleModalView = (selectedItem: string) => {
if (!props.isTrackPanelOpened) {
props.toggleTrackPanel(true);
if (!isTrackPanelOpened) {
dispatch(toggleTrackPanel(true));
}
if (isDrawerOpened) {
dispatch(toggleDrawer(false));
}
if (selectedItem === props.trackPanelModalView) {
props.closeTrackPanelModal();
if (selectedItem === trackPanelModalView) {
dispatch(closeTrackPanelModal());
} else {
props.openTrackPanelModal(selectedItem);
dispatch(openTrackPanelModal(selectedItem));
}
};
const getViewIconStatus = (selectedItem: string) => {
return selectedItem === props.trackPanelModalView &&
props.isTrackPanelOpened
return selectedItem === trackPanelModalView && isTrackPanelOpened
? Status.SELECTED
: Status.UNSELECTED;
};
......@@ -125,16 +124,4 @@ export const TrackPanelBar = (props: TrackPanelBarProps) => {
);
};
const mapStateToProps = (state: RootState) => ({
isTrackPanelModalOpened: getIsTrackPanelModalOpened(state),
isTrackPanelOpened: getIsTrackPanelOpened(state),
trackPanelModalView: getTrackPanelModalView(state)
});
const mapDispatchToProps = {
closeTrackPanelModal,
openTrackPanelModal,
toggleTrackPanel
};
export default connect(mapStateToProps, mapDispatchToProps)(TrackPanelBar);
export default TrackPanelBar;
......@@ -16,7 +16,7 @@
import { createAction } from 'typesafe-actions';
import { ThunkAction } from 'redux-thunk';
import { Action, ActionCreator } from 'redux';
import { Action } from 'redux';
import uniq from 'lodash/uniq';
import { RootState } from 'src/store';
......@@ -51,12 +51,12 @@ export const updateTrackPanelForGenome = createAction(
}
)();
export const toggleTrackPanel: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (isTrackPanelOpened: boolean) => (dispatch, getState: () => RootState) => {
export const toggleTrackPanel = (
isTrackPanelOpened: boolean
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
......@@ -74,12 +74,9 @@ export const toggleTrackPanel: ActionCreator<ThunkAction<
);
};
export const selectTrackPanelTab: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (selectedTrackPanelTab: TrackSet) => (
export const selectTrackPanelTab = (
selectedTrackPanelTab: TrackSet
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
......@@ -108,12 +105,12 @@ export const selectTrackPanelTab: ActionCreator<ThunkAction<
);
};
export const changeTrackPanelModalViewForGenome: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (trackPanelModalView: string) => (dispatch, getState: () => RootState) => {
export const changeTrackPanelModalViewForGenome = (
trackPanelModalView: string
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const activeGenomeId = getBrowserActiveGenomeId(getState());
if (!activeGenomeId) {
......@@ -130,12 +127,12 @@ export const changeTrackPanelModalViewForGenome: ActionCreator<ThunkAction<
);
};
export const updatePreviouslyViewedObjectsAndSave: ActionCreator<ThunkAction<
export const updatePreviouslyViewedObjectsAndSave = (): ThunkAction<
void,
any,
null,
Action<string>
>> = () => (dispatch, getState: () => RootState) => {
> => (dispatch, getState: () => RootState) => {
const state = getState();
const activeGenomeId = getBrowserActiveGenomeId(state);
const activeEnsObject = getBrowserActiveEnsObject(state);
......@@ -179,12 +176,12 @@ export const updatePreviouslyViewedObjectsAndSave: ActionCreator<ThunkAction<
);
};
export const changeHighlightedTrackId: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (highlightedTrackId: string) => (dispatch, getState: () => RootState) => {
export const changeHighlightedTrackId = (
highlightedTrackId: string
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const state = getState();
const activeGenomeId = getBrowserActiveGenomeId(state);
......@@ -203,12 +200,12 @@ export const changeHighlightedTrackId: ActionCreator<ThunkAction<
);
};
export const openTrackPanelModal: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (trackPanelModalView: string) => (dispatch, getState: () => RootState) => {
export const openTrackPanelModal = (
trackPanelModalView: string
): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
const state = getState();
const activeGenomeId = getBrowserActiveGenomeId(state);
......@@ -229,12 +226,12 @@ export const openTrackPanelModal: ActionCreator<ThunkAction<
);
};
export const closeTrackPanelModal: ActionCreator<ThunkAction<
export const closeTrackPanelModal = (): ThunkAction<
void,
any,
null,
Action<string>
>> = () => (dispatch, getState: () => RootState) => {
> => (dispatch, getState: () => RootState) => {
const state = getState();
const activeGenomeId = getBrowserActiveGenomeId(state);
......@@ -254,12 +251,10 @@ export const closeTrackPanelModal: ActionCreator<ThunkAction<
);
};
export const updateCollapsedTrackIds: ActionCreator<ThunkAction<
void,
any,
null,
Action<string>
>> = (payload: { trackId: string; isCollapsed: boolean }) => (
export const updateCollapsedTrackIds = (payload: {
trackId: string;
isCollapsed: boolean;
}): ThunkAction<void, any, null, Action<string>> => (
dispatch,
getState: () => RootState
) => {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment