fix: Remove trash data from redux storage after updates (#1358)
* Remove tash data from redux storage after updates * Imprelemnted more unit tests * Remove missing comment Co-authored-by: Danny Brown <danny.ri.brown@gmail.com>
This commit is contained in:
parent
225da81135
commit
7b2d44f2c1
@ -11,20 +11,63 @@ import {
|
||||
SET_VIEWPORT_LAYOUT_AND_DATA,
|
||||
} from './../constants/ActionTypes.js';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
export const DEFAULT_STATE = {
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
activeViewportIndex: 0,
|
||||
layout: {
|
||||
viewports: [
|
||||
{
|
||||
// plugin: 'cornerstone',
|
||||
},
|
||||
],
|
||||
viewports: [{}],
|
||||
},
|
||||
viewportSpecificData: {},
|
||||
};
|
||||
|
||||
/**
|
||||
* Take the new number of rows and columns, delete all not used viewport data and also set
|
||||
* active viewport as default in case current one is not available anymore.
|
||||
*
|
||||
* @param {Number} numRows
|
||||
* @param {Number} numColumns
|
||||
* @param {Object} currentViewportSpecificData
|
||||
* @returns
|
||||
*/
|
||||
const findActiveViewportSpecificData = (
|
||||
numRows,
|
||||
numColumns,
|
||||
currentViewportSpecificData = {}
|
||||
) => {
|
||||
const numberOfViewports = numRows * numColumns;
|
||||
const viewportSpecificData = cloneDeep(currentViewportSpecificData);
|
||||
|
||||
if (numberOfViewports < Object.keys(viewportSpecificData).length) {
|
||||
Object.keys(viewportSpecificData).forEach(key => {
|
||||
if (key > numberOfViewports - 1) {
|
||||
delete viewportSpecificData[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return viewportSpecificData;
|
||||
};
|
||||
/**
|
||||
* Take new number of rows and columns and make sure the current active viewport index is still available, if not, return the default
|
||||
*
|
||||
* @param {Number} numRows
|
||||
* @param {Number} numColumns
|
||||
* @param {Number} currentActiveViewportIndex
|
||||
* @returns
|
||||
*/
|
||||
const getActiveViewportIndex = (
|
||||
numRows,
|
||||
numColumns,
|
||||
currentActiveViewportIndex
|
||||
) => {
|
||||
const numberOfViewports = numRows * numColumns;
|
||||
|
||||
return currentActiveViewportIndex > numberOfViewports - 1
|
||||
? DEFAULT_STATE.activeViewportIndex
|
||||
: currentActiveViewportIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* The definition of a viewport action.
|
||||
*
|
||||
@ -50,7 +93,12 @@ const viewports = (state = DEFAULT_STATE, action) => {
|
||||
* @return {Object} New state.
|
||||
*/
|
||||
case SET_VIEWPORT_ACTIVE: {
|
||||
return { ...state, activeViewportIndex: action.viewportIndex };
|
||||
const activeViewportIndex = getActiveViewportIndex(
|
||||
state.numRows,
|
||||
state.numColumns,
|
||||
action.viewportIndex
|
||||
);
|
||||
return { ...state, activeViewportIndex };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,11 +107,25 @@ const viewports = (state = DEFAULT_STATE, action) => {
|
||||
* @return {Object} New state.
|
||||
*/
|
||||
case SET_VIEWPORT_LAYOUT: {
|
||||
const { numRows, numColumns } = action;
|
||||
const viewportSpecificData = findActiveViewportSpecificData(
|
||||
numRows,
|
||||
numColumns,
|
||||
state.viewportSpecificData
|
||||
);
|
||||
const activeViewportIndex = getActiveViewportIndex(
|
||||
numRows,
|
||||
numColumns,
|
||||
state.activeViewportIndex
|
||||
);
|
||||
|
||||
return {
|
||||
...state,
|
||||
numRows: action.numRows,
|
||||
numColumns: action.numColumns,
|
||||
layout: { viewports: [...action.viewports] },
|
||||
viewportSpecificData,
|
||||
activeViewportIndex,
|
||||
};
|
||||
}
|
||||
|
||||
@ -73,12 +135,25 @@ const viewports = (state = DEFAULT_STATE, action) => {
|
||||
* @return {Object} New state.
|
||||
*/
|
||||
case SET_VIEWPORT_LAYOUT_AND_DATA: {
|
||||
const { numRows, numColumns } = action;
|
||||
const viewportSpecificData = findActiveViewportSpecificData(
|
||||
numRows,
|
||||
numColumns,
|
||||
action.viewportSpecificData
|
||||
);
|
||||
const activeViewportIndex = getActiveViewportIndex(
|
||||
numRows,
|
||||
numColumns,
|
||||
state.activeViewportIndex
|
||||
);
|
||||
|
||||
return {
|
||||
...state,
|
||||
numRows: action.numRows,
|
||||
numColumns: action.numColumns,
|
||||
layout: { viewports: [...action.viewports] },
|
||||
viewportSpecificData: cloneDeep(action.viewportSpecificData),
|
||||
viewportSpecificData,
|
||||
activeViewportIndex,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,35 +1,61 @@
|
||||
// https://medium.com/@netxm/testing-redux-reducers-with-jest-6653abbfe3e1
|
||||
import reducer from './viewports.js';
|
||||
import { Reducer } from 'redux-testkit';
|
||||
|
||||
import reducer, { DEFAULT_STATE } from './viewports.js';
|
||||
import * as types from './../constants/ActionTypes.js';
|
||||
|
||||
describe('viewports reducer', () => {
|
||||
it('should return the initial state', () => {
|
||||
expect(reducer(undefined, {})).toEqual({
|
||||
activeViewportIndex: 0,
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
layout: {
|
||||
viewports: [{}],
|
||||
},
|
||||
viewportSpecificData: {},
|
||||
});
|
||||
expect(reducer(undefined, {})).toEqual(DEFAULT_STATE);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_ACTIVE', () => {
|
||||
const setViewportActiveAction = {
|
||||
it('should handle SET_VIEWPORT_ACTIVE with inexistent viewport index', () => {
|
||||
const initialState = {
|
||||
numRows: 4,
|
||||
numColumns: 4,
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_ACTIVE,
|
||||
viewportIndex: 100,
|
||||
};
|
||||
|
||||
const updatedState = reducer({}, setViewportActiveAction);
|
||||
const expectedToChangeInState = {
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
expect(updatedState.activeViewportIndex).toEqual(
|
||||
setViewportActiveAction.viewportIndex
|
||||
);
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toChangeInState(expectedToChangeInState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_ACTIVE with existent viewport index', () => {
|
||||
const initialState = {
|
||||
numRows: 4,
|
||||
numColumns: 4,
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_ACTIVE,
|
||||
viewportIndex: 5,
|
||||
};
|
||||
|
||||
const expectedToChangeInState = {
|
||||
activeViewportIndex: 5,
|
||||
};
|
||||
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toChangeInState(expectedToChangeInState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_LAYOUT', () => {
|
||||
const setViewportLayoutAction = {
|
||||
const initialState = DEFAULT_STATE;
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_LAYOUT,
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
@ -43,18 +69,193 @@ describe('viewports reducer', () => {
|
||||
],
|
||||
};
|
||||
|
||||
const updatedState = reducer({}, setViewportLayoutAction);
|
||||
const expectedToChangeInState = {
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
layout: {
|
||||
viewports: [
|
||||
{
|
||||
plugin: 'cornerstone',
|
||||
},
|
||||
{
|
||||
plugin: 'vtk',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
expect(updatedState.numRows).toEqual(setViewportLayoutAction.numRows);
|
||||
expect(updatedState.numColumns).toEqual(setViewportLayoutAction.numColumns);
|
||||
expect(updatedState.layout.viewports).toEqual(
|
||||
setViewportLayoutAction.viewports
|
||||
);
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toChangeInState(expectedToChangeInState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_LAYOUT when we reduce the number of viewports', () => {
|
||||
const initialState = {
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'viewportData0' },
|
||||
1: { viewportData1: 'viewportData1' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_LAYOUT,
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
viewports: [],
|
||||
};
|
||||
|
||||
const expectedState = {
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'viewportData0' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toReturnState(expectedState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_LAYOUT_AND_DATA', () => {
|
||||
const initialState = {
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'data0' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'cornerstone' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_LAYOUT_AND_DATA,
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
viewports: [{ plugin: 'cornerstone' }, { plugin: 'cornerstone' }],
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'NEWdata0' },
|
||||
1: { viewportData1: 'NEWdata1' },
|
||||
},
|
||||
};
|
||||
|
||||
const expectedState = {
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'NEWdata0' },
|
||||
1: { viewportData1: 'NEWdata1' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'cornerstone' }, { plugin: 'cornerstone' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toReturnState(expectedState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT_LAYOUT_AND_DATA when we reduce the number of viewports', () => {
|
||||
const initialState = {
|
||||
numRows: 1,
|
||||
numColumns: 3,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'vtkData0' },
|
||||
1: { viewportData1: 'vtkData1' },
|
||||
2: { viewportData2: 'vtkData2' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'vtk' }, { plugin: 'vtk' }, { plugin: 'vtk' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT_LAYOUT_AND_DATA,
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
viewports: [{ plugin: 'cornerstone' }],
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'cornerstoneData0' },
|
||||
},
|
||||
};
|
||||
|
||||
const expectedState = {
|
||||
numRows: 1,
|
||||
numColumns: 1,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'cornerstoneData0' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'cornerstone' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toReturnState(expectedState);
|
||||
});
|
||||
|
||||
it('should handle SET_VIEWPORT when we only set one viewport specific data', () => {
|
||||
const initialState = {
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'data0' },
|
||||
1: { viewportData1: 'data1' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'cornerstone' }, { plugin: 'cornerstone' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
const action = {
|
||||
type: types.SET_VIEWPORT,
|
||||
viewportIndex: 1,
|
||||
viewportSpecificData: {
|
||||
viewportData1: 'NEWdata1',
|
||||
},
|
||||
};
|
||||
|
||||
const expectedState = {
|
||||
numRows: 1,
|
||||
numColumns: 2,
|
||||
viewportSpecificData: {
|
||||
0: { viewportData0: 'data0' },
|
||||
1: { viewportData1: 'NEWdata1' },
|
||||
},
|
||||
layout: {
|
||||
viewports: [{ plugin: 'cornerstone' }, { plugin: 'cornerstone' }],
|
||||
},
|
||||
activeViewportIndex: 0,
|
||||
};
|
||||
|
||||
Reducer(reducer)
|
||||
.withState(initialState)
|
||||
.expect(action)
|
||||
.toReturnState(expectedState);
|
||||
});
|
||||
|
||||
// If there were previous keys, this would have
|
||||
// "merge" behavior, not a clear & set
|
||||
// May be worth another test?
|
||||
it('should handle SET_VIEWPORT', () => {
|
||||
const viewportToSet = 0;
|
||||
const setViewportAction = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user