This commit is contained in:
Pablo Alonso 2015-10-16 21:28:45 +00:00
commit ad54a58a2c
3 changed files with 71 additions and 0 deletions

View File

@ -3,6 +3,7 @@ const ActionTypes = {
RESET: 'RESET',
ROLLBACK: 'ROLLBACK',
COMMIT: 'COMMIT',
IMPORT_STATE: 'IMPORT_STATE',
SWEEP: 'SWEEP',
TOGGLE_ACTION: 'TOGGLE_ACTION',
JUMP_TO_STATE: 'JUMP_TO_STATE',
@ -121,6 +122,16 @@ function liftReducer(reducer, initialState) {
currentStateIndex = 0;
timestamps = [liftedAction.timestamp];
break;
case ActionTypes.IMPORT_STATE:
({
stagedActions,
skippedActions,
computedStates,
currentStateIndex,
monitorState,
timestamps
} = liftedAction.nextLiftedState);
break;
case ActionTypes.ROLLBACK:
stagedActions = [INIT_ACTION];
skippedActions = {};
@ -258,6 +269,9 @@ export const ActionCreators = {
commit() {
return { type: ActionTypes.COMMIT, timestamp: Date.now() };
},
importState(nextLiftedState) {
return { type: ActionTypes.IMPORT_STATE, nextLiftedState };
},
sweep() {
return { type: ActionTypes.SWEEP };
},

View File

@ -1,3 +1,4 @@
/* eslint-disable no-alert */
import React, { PropTypes, findDOMNode, Component } from 'react';
import LogMonitorEntry from './LogMonitorEntry';
import LogMonitorButton from './LogMonitorButton';
@ -118,6 +119,21 @@ export default class LogMonitor extends Component {
this.props.commit();
}
handleExport() {
window.prompt('Current state\'s schema', JSON.stringify(this.props.store.getState()));
}
handleImport() {
try {
let nextLiftedState = window.prompt('Please paste a valid action log');
if (nextLiftedState) {
this.props.importState(JSON.parse(nextLiftedState));
}
} catch (err) {
console.warn('There was an error parsing the new state. Please enter a valid schema.');
}
}
handleToggleAction(index) {
this.props.toggleAction(index);
}
@ -184,6 +200,8 @@ export default class LogMonitor extends Component {
<LogMonitorButton theme={theme} onClick={::this.handleRollback} enabled={computedStates.length}>Revert</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleSweep} enabled={Object.keys(skippedActions).some(key => skippedActions[key])}>Sweep</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleCommit} enabled={computedStates.length > 1}>Commit</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleImport} enabled={true}>Import</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleExport} enabled={computedStates.length}>Export</LogMonitorButton>
</div>
<div style={styles.elements} ref="elements">
{elements}
@ -192,3 +210,4 @@ export default class LogMonitor extends Component {
);
}
}
/* eslint-enable no-alert */

View File

@ -243,4 +243,42 @@ describe('devTools', () => {
monitoredDevToolsStore.dispatch(ActionCreators.jumpToState(3));
expect(reducerCalls).toBe(4);
});
describe('Import State', () => {
let monitoredStore;
let monitoredDevToolsStore;
let exportedState;
beforeEach(() => {
monitoredStore = devTools()(createStore)(counter);
monitoredDevToolsStore = monitoredStore.devToolsStore;
// Set up state to export
monitoredStore.dispatch({ type: 'INCREMENT' });
monitoredStore.dispatch({ type: 'INCREMENT' });
monitoredStore.dispatch({ type: 'INCREMENT' });
exportedState = monitoredDevToolsStore.getState();
});
it('should replay all the steps when a state is imported', () => {
let importMonitoredStore = devTools()(createStore)(counter);
let importMonitoredDevToolsStore = importMonitoredStore.devToolsStore;
// Import exported state
importMonitoredDevToolsStore.dispatch(ActionCreators.importState(exportedState));
expect(importMonitoredDevToolsStore.getState()).toEqual(exportedState);
});
it('should replace the existing action log with the one imported', () => {
let importMonitoredStore = devTools()(createStore)(counter);
let importMonitoredDevToolsStore = importMonitoredStore.devToolsStore;
importMonitoredStore.dispatch({ type: 'DECREMENT' });
importMonitoredStore.dispatch({ type: 'DECREMENT' });
// Import exported state
importMonitoredDevToolsStore.dispatch(ActionCreators.importState(exportedState));
expect(importMonitoredDevToolsStore.getState()).toEqual(exportedState);
});
});
});