diff --git a/__tests__/src/actions/companionWindow.test.js b/__tests__/src/actions/companionWindow.test.js index 183949b736913b742482af63cadf42810fb99f51..0e7a1df61a78a41829ee8243f8ea8825d870fc3b 100644 --- a/__tests__/src/actions/companionWindow.test.js +++ b/__tests__/src/actions/companionWindow.test.js @@ -90,9 +90,10 @@ describe('companionWindow actions', () => { describe('removeCompanionWindow', () => { it('should return correct action object', () => { - const action = actions.removeCompanionWindow('cw-123'); + const action = actions.removeCompanionWindow('window', 'cw-123'); expect(action.type).toBe(ActionTypes.REMOVE_COMPANION_WINDOW); expect(action.id).toBe('cw-123'); + expect(action.windowId).toBe('window'); }); }); }); diff --git a/__tests__/src/actions/window.test.js b/__tests__/src/actions/window.test.js index c144d7d2d94b9bdef18563b8e30ba7ccc04fd26c..a447ebc0a4a6e7cd4b60ef8bc53f890b7b9976ce 100644 --- a/__tests__/src/actions/window.test.js +++ b/__tests__/src/actions/window.test.js @@ -55,8 +55,24 @@ describe('window actions', () => { const expectedAction = { type: ActionTypes.REMOVE_WINDOW, windowId: id, + companionWindowIds: ['a', 'b', 'c'], }; - expect(actions.removeWindow(id)).toEqual(expectedAction); + + const mockState = { + windows: { + abc123: { companionWindowIds: ['a', 'b', 'c'] }, + }, + companionWindows: {}, + }; + + const mockDispatch = jest.fn(() => ({})); + const mockGetState = jest.fn(() => mockState); + const thunk = actions.removeWindow(id); + + thunk(mockDispatch, mockGetState); + + const action = mockDispatch.mock.calls[0][0]; + expect(action).toEqual(expectedAction); }); }); diff --git a/__tests__/src/components/CompanionWindow.test.js b/__tests__/src/components/CompanionWindow.test.js index 3666ce275ee5e3ba83eb39dfee0b19bfc95c421f..a88faa33063a8730f3a60c4547a5a799daa610fe 100644 --- a/__tests__/src/components/CompanionWindow.test.js +++ b/__tests__/src/components/CompanionWindow.test.js @@ -45,7 +45,6 @@ describe('CompanionWindow', () => { const closeButton = companionWindow.find('WithStyles(IconButton)[aria-label="closeCompanionWindow"]'); closeButton.simulate('click'); expect(removeCompanionWindowEvent).toHaveBeenCalledTimes(1); - expect(removeCompanionWindowEvent).toHaveBeenCalledWith('x', 'abc123'); }); }); diff --git a/__tests__/src/components/WindowTopBar.test.js b/__tests__/src/components/WindowTopBar.test.js index 27aff2536a1ba090a803420df5a6d98f2b114490..f7bb55a46743d12c27c1d4e732163c37b49fa05b 100644 --- a/__tests__/src/components/WindowTopBar.test.js +++ b/__tests__/src/components/WindowTopBar.test.js @@ -22,7 +22,7 @@ function createWrapper(props) { maximizeWindow={() => {}} maximized={false} minimizeWindow={() => {}} - closeWindow={() => {}} + removeWindow={() => {}} toggleWindowSideBar={() => {}} {...props} />, @@ -63,9 +63,9 @@ describe('WindowTopBar', () => { }); it('passes correct props to <Button/>', () => { - const closeWindow = jest.fn(); - const wrapper = createWrapper({ closeWindow }); - expect(wrapper.find(IconButton).last().props().onClick).toBe(closeWindow); + const removeWindow = jest.fn(); + const wrapper = createWrapper({ removeWindow }); + expect(wrapper.find(IconButton).last().props().onClick).toBe(removeWindow); }); it('passes correct props to <Button/>', () => { diff --git a/__tests__/src/reducers/companionWindows.test.js b/__tests__/src/reducers/companionWindows.test.js index 9f33e9ecf64c6c1aa05470a9149c470e913678af..fc830f46e9343d4cb2ab47c2ad519818425d9f47 100644 --- a/__tests__/src/reducers/companionWindows.test.js +++ b/__tests__/src/reducers/companionWindows.test.js @@ -76,4 +76,21 @@ describe('companionWindowsReducer', () => { expect(companionWindowsReducer(beforeState, action)).toEqual(expectedState); }); }); + + describe('REMOVE_WINDOW', () => { + it('should remove a companion window', () => { + const action = { + type: ActionTypes.REMOVE_WINDOW, + id: 'abc123', + companionWindowIds: ['a', 'b'], + }; + const beforeState = { + a: {}, + b: {}, + c: {}, + }; + const expectedState = { c: {} }; + expect(companionWindowsReducer(beforeState, action)).toEqual(expectedState); + }); + }); }); diff --git a/__tests__/src/reducers/windows.test.js b/__tests__/src/reducers/windows.test.js index d39aad6e4f52231ac67ffe8649af5fbfbf33ae02..a7ee9845d904003b18158d063270fe9ce40accb7 100644 --- a/__tests__/src/reducers/windows.test.js +++ b/__tests__/src/reducers/windows.test.js @@ -293,4 +293,23 @@ describe('windows reducer', () => { }, }); }); + + it('should handle REMOVE_COMPANION_WINDOW', () => { + // on the right, just tacks the new id on + expect(windowsReducer({ + abc123: { + id: 'abc123', + companionWindowIds: ['123', 'xyz'], + }, + }, { + type: ActionTypes.REMOVE_COMPANION_WINDOW, + id: 'xyz', + windowId: 'abc123', + })).toEqual({ + abc123: { + id: 'abc123', + companionWindowIds: ['123'], + }, + }); + }); }); diff --git a/src/components/CompanionWindow.js b/src/components/CompanionWindow.js index 86eb876822abe9362fb38b7741553253ab564e7a..b474e90faf63174b955908be5394a82cab079023 100644 --- a/src/components/CompanionWindow.js +++ b/src/components/CompanionWindow.js @@ -71,7 +71,7 @@ export class CompanionWindow extends Component { <IconButton aria-label={t('closeCompanionWindow')} className={classes.closeButton} - onClick={() => { onCloseClick(windowId, id); }} + onClick={onCloseClick} > <CloseIcon /> </IconButton> diff --git a/src/components/WindowTopBar.js b/src/components/WindowTopBar.js index 2faea219b2fc8f8279f26d4c9ddc248e08681f48..7488297ee7371d3ef8a2418c2f1f0028f94bd8a0 100644 --- a/src/components/WindowTopBar.js +++ b/src/components/WindowTopBar.js @@ -24,7 +24,7 @@ export class WindowTopBar extends Component { */ render() { const { - closeWindow, windowId, classes, toggleWindowSideBar, t, manifestTitle, + removeWindow, windowId, classes, toggleWindowSideBar, t, manifestTitle, maximizeWindow, maximized, minimizeWindow, } = this.props; return ( @@ -56,7 +56,7 @@ export class WindowTopBar extends Component { color="inherit" className={ns('window-close')} aria-label={t('closeWindow')} - onClick={closeWindow} + onClick={removeWindow} > <CloseIcon /> </IconButton> @@ -71,7 +71,7 @@ WindowTopBar.propTypes = { maximizeWindow: PropTypes.func, maximized: PropTypes.bool, minimizeWindow: PropTypes.func, - closeWindow: PropTypes.func.isRequired, + removeWindow: PropTypes.func.isRequired, windowId: PropTypes.string.isRequired, classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types toggleWindowSideBar: PropTypes.func.isRequired, diff --git a/src/containers/CompanionWindow.js b/src/containers/CompanionWindow.js index b49ca85c4803c54a6d2ce43a4e97ef6572a577b5..ce99afa5d6175840757999568df21bb4ae1d1fe6 100644 --- a/src/containers/CompanionWindow.js +++ b/src/containers/CompanionWindow.js @@ -27,10 +27,12 @@ const mapStateToProps = (state, { id, windowId }) => { * @memberof CompanionWindow * @private */ -const mapDispatchToProps = { - onCloseClick: actions.closeCompanionWindow, - updateCompanionWindow: actions.updateCompanionWindow, -}; +const mapDispatchToProps = (dispatch, { windowId, id }) => ({ + onCloseClick: () => dispatch( + actions.removeCompanionWindow(windowId, id), + ), + updateCompanionWindow: (...args) => dispatch(actions.updateCompanionWindow(...args)), +}); /** * diff --git a/src/containers/WindowTopBar.js b/src/containers/WindowTopBar.js index 27e880e45e7b572e68e23d8d6998ae703f1f0b56..d63693b48eeb65dfb138509ecfc93b55f15c4090 100644 --- a/src/containers/WindowTopBar.js +++ b/src/containers/WindowTopBar.js @@ -19,7 +19,7 @@ const mapStateToProps = (state, { windowId }) => ({ * @private */ const mapDispatchToProps = (dispatch, { windowId }) => ({ - closeWindow: () => dispatch(actions.closeWindow(windowId)), + removeWindow: () => dispatch(actions.removeWindow(windowId)), maximizeWindow: () => dispatch(actions.maximizeWindow(windowId)), minimizeWindow: () => dispatch(actions.minimizeWindow(windowId)), toggleWindowSideBar: () => dispatch(actions.toggleWindowSideBar(windowId)), diff --git a/src/state/actions/companionWindow.js b/src/state/actions/companionWindow.js index 044bbc648e4e5811b361fa1b2534d186859f9b2d..02ef3a2737fe67911a4e476b25e77a189200194c 100644 --- a/src/state/actions/companionWindow.js +++ b/src/state/actions/companionWindow.js @@ -1,6 +1,5 @@ import uuid from 'uuid/v4'; import ActionTypes from './action-types'; -import { updateWindow } from './window'; const defaultProps = { content: null, @@ -34,18 +33,6 @@ export function updateCompanionWindow(windowId, id, payload) { } /** */ -export function removeCompanionWindow(id) { - return { type: ActionTypes.REMOVE_COMPANION_WINDOW, id }; -} - -/** -* Close companion window and remove reference from window -*/ -export function closeCompanionWindow(windowId, companionWindowId) { - return (dispatch, getState) => { - dispatch(removeCompanionWindow(companionWindowId)); - const companionWindowIds = getState().windows[windowId].companionWindowIds - .filter(id => id !== companionWindowId); - dispatch(updateWindow(windowId, { companionWindowIds })); - }; +export function removeCompanionWindow(windowId, id) { + return { type: ActionTypes.REMOVE_COMPANION_WINDOW, id, windowId }; } diff --git a/src/state/actions/window.js b/src/state/actions/window.js index b966c2dca801ab5818894cba3d3a57618c536a46..cc195dfb2ccd2275419d3647a78abc01aa5c9a32 100644 --- a/src/state/actions/window.js +++ b/src/state/actions/window.js @@ -1,6 +1,5 @@ import uuid from 'uuid/v4'; import ActionTypes from './action-types'; -import { removeCompanionWindow } from './companionWindow'; /** * focusWindow - action creator @@ -75,7 +74,12 @@ export function setCompanionAreaOpen(id, companionAreaOpen) { * @memberof ActionCreators */ export function removeWindow(windowId) { - return { type: ActionTypes.REMOVE_WINDOW, windowId }; + return (dispatch, getState) => { + const { windows } = getState(); + const { companionWindowIds } = windows[windowId]; + + dispatch({ type: ActionTypes.REMOVE_WINDOW, windowId, companionWindowIds }); + }; } /** @@ -99,17 +103,6 @@ export function setWindowSideBarPanel(windowId, panelType) { return { type: ActionTypes.SET_WINDOW_SIDE_BAR_PANEL, windowId, panelType }; } -/** -* Clean up state and remove window -*/ -export function closeWindow(windowId) { - return (dispatch, getState) => { - const { companionWindowIds } = getState().windows[windowId]; - companionWindowIds.map(id => dispatch(removeCompanionWindow(id))); - dispatch(removeWindow(windowId)); - }; -} - /** * setWindowThumbnailPosition - action creator * diff --git a/src/state/reducers/companionWindows.js b/src/state/reducers/companionWindows.js index e3d43b9809e8dbb417b9e4eef182e5ca464f21ca..6cd71b9595e82a1972742b110b2909a58c3e12e9 100644 --- a/src/state/reducers/companionWindows.js +++ b/src/state/reducers/companionWindows.js @@ -15,6 +15,9 @@ export function companionWindowsReducer(state = {}, action) { return newState; }, state); + case ActionTypes.REMOVE_WINDOW: + return action.companionWindowIds.reduce((newState, id) => removeIn(newState, [id]), state); + case ActionTypes.UPDATE_COMPANION_WINDOW: return updateIn(state, [action.id], orig => merge(orig, action.payload)); diff --git a/src/state/reducers/windows.js b/src/state/reducers/windows.js index 8a08187677e67077b13efd5895d4dd9a639319da..9ac1ce28af442ddbac7bf5c3dd2c0de172e64c50 100644 --- a/src/state/reducers/windows.js +++ b/src/state/reducers/windows.js @@ -117,6 +117,15 @@ export const windowsReducer = (state = {}, action) => { companionWindowIds: state[action.windowId].companionWindowIds.concat([action.id]), }, }; + case ActionTypes.REMOVE_COMPANION_WINDOW: + return { + ...state, + [action.windowId]: { + ...state[action.windowId], + companionWindowIds: state[action.windowId] + .companionWindowIds.filter(id => id !== action.id), + }, + }; default: return state; }