mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-22 09:36:43 +03:00
Refactor
This commit is contained in:
parent
26c66fef63
commit
4428e8818d
|
@ -28,8 +28,8 @@
|
||||||
"node-libs-browser": "^0.5.2",
|
"node-libs-browser": "^0.5.2",
|
||||||
"react-dock": "^0.1.0",
|
"react-dock": "^0.1.0",
|
||||||
"react-hot-loader": "^1.3.0",
|
"react-hot-loader": "^1.3.0",
|
||||||
"redux-devtools": "^3.0.0-alpha-6",
|
"redux-devtools": "^3.0.0-alpha-7",
|
||||||
"redux-devtools-log-monitor": "^1.0.0-alpha-6",
|
"redux-devtools-log-monitor": "^1.0.0-alpha-7",
|
||||||
"webpack": "^1.9.11",
|
"webpack": "^1.9.11",
|
||||||
"webpack-dev-server": "^1.9.0"
|
"webpack-dev-server": "^1.9.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import DevTools from '../containers/DevTools';
|
||||||
|
|
||||||
const finalCreateStore = compose(
|
const finalCreateStore = compose(
|
||||||
applyMiddleware(thunk),
|
applyMiddleware(thunk),
|
||||||
DevTools.enhance,
|
DevTools.instrument(),
|
||||||
persistState(
|
persistState(
|
||||||
window.location.href.match(
|
window.location.href.match(
|
||||||
/[?&]debug_session=([^&]+)\b/
|
/[?&]debug_session=([^&]+)\b/
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
export default function bindActionCreatorsRecursively(actionCreators, dispatch) {
|
export default function bindActionCreatorsDeep(actionCreators, dispatch) {
|
||||||
return Object.keys(actionCreators).reduce((result, key) => {
|
return Object.keys(actionCreators).reduce((result, key) => {
|
||||||
if (!actionCreators[key]) {
|
if (!actionCreators[key]) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (typeof actionCreators[key]) {
|
switch (typeof actionCreators[key]) {
|
||||||
case 'object':
|
case 'object':
|
||||||
result[key] = bindActionCreatorsRecursively(actionCreators[key], dispatch);
|
result[key] = bindActionCreatorsDeep(actionCreators[key], dispatch);
|
||||||
break;
|
break;
|
||||||
case 'function':
|
case 'function':
|
||||||
result[key] = bindActionCreators(actionCreators[key], dispatch);
|
result[key] = bindActionCreators(actionCreators[key], dispatch);
|
|
@ -1,7 +1,7 @@
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import bindActionCreatorsRecursively from './bindActionCreatorsRecursively';
|
import bindActionCreatorsDeep from './bindActionCreatorsDeep';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { ActionCreators as devToolsActionCreators } from './enhance';
|
import { ActionCreators as historyActionCreators } from './instrument';
|
||||||
|
|
||||||
export default function connectMonitor({
|
export default function connectMonitor({
|
||||||
component,
|
component,
|
||||||
|
@ -10,15 +10,15 @@ export default function connectMonitor({
|
||||||
}) {
|
}) {
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
devToolsState: state.devToolsState,
|
historyState: state.historyState,
|
||||||
monitorState: state.monitorState
|
monitorState: state.monitorState
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
devToolsActions: bindActionCreators(devToolsActionCreators, dispatch),
|
historyActions: bindActionCreators(historyActionCreators, dispatch),
|
||||||
monitorActions: bindActionCreatorsRecursively(actionCreators, dispatch)
|
monitorActions: bindActionCreatorsDeep(actionCreators, dispatch)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { Component, PropTypes } from 'react';
|
import React, { Component, PropTypes } from 'react';
|
||||||
import enhance from './enhance';
|
import instrument from './instrument';
|
||||||
import connectMonitor from './connectMonitor';
|
import connectMonitor from './connectMonitor';
|
||||||
|
|
||||||
export default function createDevTools(monitor) {
|
export default function createDevTools(monitor) {
|
||||||
|
@ -10,12 +10,12 @@ export default function createDevTools(monitor) {
|
||||||
store: PropTypes.object.isRequired
|
store: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static enhance = enhance(Monitor.reducer);
|
static instrument = () => instrument(Monitor.reducer);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Monitor {...this.props}
|
<Monitor {...this.props}
|
||||||
store={this.context.store.devToolsStore} />
|
store={this.context.store.instrumentedStore} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export { default, ActionCreators, ActionTypes } from './enhance';
|
export { default as instrument, ActionTypes } from './instrument';
|
||||||
export { default as persistState } from './persistState';
|
export { default as persistState } from './persistState';
|
||||||
export { default as createDevTools } from './createDevTools';
|
export { default as createDevTools } from './createDevTools';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
const ActionTypes = {
|
export const ActionTypes = {
|
||||||
PERFORM_ACTION: 'PERFORM_ACTION',
|
PERFORM_ACTION: 'PERFORM_ACTION',
|
||||||
RESET: 'RESET',
|
RESET: 'RESET',
|
||||||
ROLLBACK: 'ROLLBACK',
|
ROLLBACK: 'ROLLBACK',
|
||||||
|
@ -10,10 +10,41 @@ const ActionTypes = {
|
||||||
JUMP_TO_STATE: 'JUMP_TO_STATE'
|
JUMP_TO_STATE: 'JUMP_TO_STATE'
|
||||||
};
|
};
|
||||||
|
|
||||||
const INIT_ACTION = {
|
/**
|
||||||
type: '@@INIT'
|
* Action creators to change the History state.
|
||||||
|
*/
|
||||||
|
export const ActionCreators = {
|
||||||
|
performAction(action) {
|
||||||
|
return { type: ActionTypes.PERFORM_ACTION, action, timestamp: Date.now() };
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
return { type: ActionTypes.RESET, timestamp: Date.now() };
|
||||||
|
},
|
||||||
|
|
||||||
|
rollback() {
|
||||||
|
return { type: ActionTypes.ROLLBACK, timestamp: Date.now() };
|
||||||
|
},
|
||||||
|
|
||||||
|
commit() {
|
||||||
|
return { type: ActionTypes.COMMIT, timestamp: Date.now() };
|
||||||
|
},
|
||||||
|
|
||||||
|
sweep() {
|
||||||
|
return { type: ActionTypes.SWEEP };
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleAction(index) {
|
||||||
|
return { type: ActionTypes.TOGGLE_ACTION, index };
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpToState(index) {
|
||||||
|
return { type: ActionTypes.JUMP_TO_STATE, index };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const INIT_ACTION = { type: '@@INIT' };
|
||||||
|
|
||||||
function toggle(obj, key) {
|
function toggle(obj, key) {
|
||||||
const clone = { ...obj };
|
const clone = { ...obj };
|
||||||
if (clone[key]) {
|
if (clone[key]) {
|
||||||
|
@ -52,8 +83,6 @@ function computeNextEntry(reducer, action, state, error) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the reducer on all actions to get a fresh computation log.
|
* Runs the reducer on all actions to get a fresh computation log.
|
||||||
* It's probably a good idea to do this only if the code has changed,
|
|
||||||
* but until we have some tests we'll just do it every time an action fires.
|
|
||||||
*/
|
*/
|
||||||
function recomputeStates(reducer, committedState, stagedActions, skippedActions) {
|
function recomputeStates(reducer, committedState, stagedActions, skippedActions) {
|
||||||
const computedStates = [];
|
const computedStates = [];
|
||||||
|
@ -77,10 +106,10 @@ function recomputeStates(reducer, committedState, stagedActions, skippedActions)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifts the app state reducer into a DevTools state reducer.
|
* Creates a history state reducer from an app's reducer.
|
||||||
*/
|
*/
|
||||||
function createDevToolsStateReducer(reducer, initialCommittedState) {
|
function createHistoryReducer(reducer, initialCommittedState) {
|
||||||
const initialState = {
|
const initialHistoryState = {
|
||||||
committedState: initialCommittedState,
|
committedState: initialCommittedState,
|
||||||
stagedActions: [INIT_ACTION],
|
stagedActions: [INIT_ACTION],
|
||||||
skippedActions: {},
|
skippedActions: {},
|
||||||
|
@ -89,9 +118,9 @@ function createDevToolsStateReducer(reducer, initialCommittedState) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages how the DevTools actions modify the DevTools state.
|
* Manages how the history actions modify the history state.
|
||||||
*/
|
*/
|
||||||
return function devToolsState(state = initialState, action) {
|
return (historyState = initialHistoryState, historyAction) => {
|
||||||
let shouldRecomputeStates = true;
|
let shouldRecomputeStates = true;
|
||||||
let {
|
let {
|
||||||
committedState,
|
committedState,
|
||||||
|
@ -100,34 +129,34 @@ function createDevToolsStateReducer(reducer, initialCommittedState) {
|
||||||
computedStates,
|
computedStates,
|
||||||
currentStateIndex,
|
currentStateIndex,
|
||||||
timestamps
|
timestamps
|
||||||
} = state;
|
} = historyState;
|
||||||
|
|
||||||
switch (action.type) {
|
switch (historyAction.type) {
|
||||||
case ActionTypes.RESET:
|
case ActionTypes.RESET:
|
||||||
committedState = initialState;
|
committedState = initialCommittedState;
|
||||||
stagedActions = [INIT_ACTION];
|
stagedActions = [INIT_ACTION];
|
||||||
skippedActions = {};
|
skippedActions = {};
|
||||||
currentStateIndex = 0;
|
currentStateIndex = 0;
|
||||||
timestamps = [action.timestamp];
|
timestamps = [historyAction.timestamp];
|
||||||
break;
|
break;
|
||||||
case ActionTypes.COMMIT:
|
case ActionTypes.COMMIT:
|
||||||
committedState = computedStates[currentStateIndex].state;
|
committedState = computedStates[currentStateIndex].state;
|
||||||
stagedActions = [INIT_ACTION];
|
stagedActions = [INIT_ACTION];
|
||||||
skippedActions = {};
|
skippedActions = {};
|
||||||
currentStateIndex = 0;
|
currentStateIndex = 0;
|
||||||
timestamps = [action.timestamp];
|
timestamps = [historyAction.timestamp];
|
||||||
break;
|
break;
|
||||||
case ActionTypes.ROLLBACK:
|
case ActionTypes.ROLLBACK:
|
||||||
stagedActions = [INIT_ACTION];
|
stagedActions = [INIT_ACTION];
|
||||||
skippedActions = {};
|
skippedActions = {};
|
||||||
currentStateIndex = 0;
|
currentStateIndex = 0;
|
||||||
timestamps = [action.timestamp];
|
timestamps = [historyAction.timestamp];
|
||||||
break;
|
break;
|
||||||
case ActionTypes.TOGGLE_ACTION:
|
case ActionTypes.TOGGLE_ACTION:
|
||||||
skippedActions = toggle(skippedActions, action.index);
|
skippedActions = toggle(skippedActions, historyAction.index);
|
||||||
break;
|
break;
|
||||||
case ActionTypes.JUMP_TO_STATE:
|
case ActionTypes.JUMP_TO_STATE:
|
||||||
currentStateIndex = action.index;
|
currentStateIndex = historyAction.index;
|
||||||
// Optimization: we know the history has not changed.
|
// Optimization: we know the history has not changed.
|
||||||
shouldRecomputeStates = false;
|
shouldRecomputeStates = false;
|
||||||
break;
|
break;
|
||||||
|
@ -142,8 +171,8 @@ function createDevToolsStateReducer(reducer, initialCommittedState) {
|
||||||
currentStateIndex++;
|
currentStateIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
stagedActions = [...stagedActions, action.action];
|
stagedActions = [...stagedActions, historyAction.action];
|
||||||
timestamps = [...timestamps, action.timestamp];
|
timestamps = [...timestamps, historyAction.timestamp];
|
||||||
|
|
||||||
// Optimization: we know that the past has not changed.
|
// Optimization: we know that the past has not changed.
|
||||||
shouldRecomputeStates = false;
|
shouldRecomputeStates = false;
|
||||||
|
@ -151,7 +180,7 @@ function createDevToolsStateReducer(reducer, initialCommittedState) {
|
||||||
const previousEntry = computedStates[computedStates.length - 1];
|
const previousEntry = computedStates[computedStates.length - 1];
|
||||||
const nextEntry = computeNextEntry(
|
const nextEntry = computeNextEntry(
|
||||||
reducer,
|
reducer,
|
||||||
action.action,
|
historyAction.action,
|
||||||
previousEntry.state,
|
previousEntry.state,
|
||||||
previousEntry.error
|
previousEntry.error
|
||||||
);
|
);
|
||||||
|
@ -182,44 +211,32 @@ function createDevToolsStateReducer(reducer, initialCommittedState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifts an app action to a DevTools action.
|
* Provides a view into the History state that matches the current app state.
|
||||||
*/
|
*/
|
||||||
function liftAction(action) {
|
function selectAppState(instrumentedState) {
|
||||||
const liftedAction = {
|
const { computedStates, currentStateIndex } = instrumentedState.historyState;
|
||||||
type: ActionTypes.PERFORM_ACTION,
|
|
||||||
action,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
return liftedAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlifts the DevTools state to the app state.
|
|
||||||
*/
|
|
||||||
function unliftState(liftedState) {
|
|
||||||
const { computedStates, currentStateIndex } = liftedState.devToolsState;
|
|
||||||
const { state } = computedStates[currentStateIndex];
|
const { state } = computedStates[currentStateIndex];
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlifts the DevTools store to act like the app's store.
|
* Deinstruments the History store to act like the app's store.
|
||||||
*/
|
*/
|
||||||
function mapToComputedStateStore(devToolsStore, wrapReducer) {
|
function selectAppStore(instrumentedStore, instrumentReducer) {
|
||||||
let lastDefinedState;
|
let lastDefinedState;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...devToolsStore,
|
...instrumentedStore,
|
||||||
|
|
||||||
devToolsStore,
|
instrumentedStore,
|
||||||
|
|
||||||
dispatch(action) {
|
dispatch(action) {
|
||||||
devToolsStore.dispatch(liftAction(action));
|
instrumentedStore.dispatch(ActionCreators.performAction(action));
|
||||||
return action;
|
return action;
|
||||||
},
|
},
|
||||||
|
|
||||||
getState() {
|
getState() {
|
||||||
const state = unliftState(devToolsStore.getState());
|
const state = selectAppState(instrumentedStore.getState());
|
||||||
if (state !== undefined) {
|
if (state !== undefined) {
|
||||||
lastDefinedState = state;
|
lastDefinedState = state;
|
||||||
}
|
}
|
||||||
|
@ -227,51 +244,25 @@ function mapToComputedStateStore(devToolsStore, wrapReducer) {
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceReducer(nextReducer) {
|
replaceReducer(nextReducer) {
|
||||||
devToolsStore.replaceReducer(wrapReducer(nextReducer));
|
instrumentedStore.replaceReducer(instrumentReducer(nextReducer));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action creators to change the DevTools state.
|
* Redux History store enhancer.
|
||||||
*/
|
*/
|
||||||
export const ActionCreators = {
|
export default function instrument(monitorReducer = () => null) {
|
||||||
reset() {
|
return createStore => (reducer, initialState) => {
|
||||||
return { type: ActionTypes.RESET, timestamp: Date.now() };
|
function instrumentReducer(r) {
|
||||||
},
|
const historyReducer = createHistoryReducer(r, initialState);
|
||||||
|
return ({ historyState, monitorState } = {}, action) => ({
|
||||||
|
historyState: historyReducer(historyState, action),
|
||||||
|
monitorState: monitorReducer(monitorState, action)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
rollback() {
|
const instrumentedStore = createStore(instrumentReducer(reducer));
|
||||||
return { type: ActionTypes.ROLLBACK, timestamp: Date.now() };
|
return selectAppStore(instrumentedStore, instrumentReducer);
|
||||||
},
|
|
||||||
|
|
||||||
commit() {
|
|
||||||
return { type: ActionTypes.COMMIT, timestamp: Date.now() };
|
|
||||||
},
|
|
||||||
|
|
||||||
sweep() {
|
|
||||||
return { type: ActionTypes.SWEEP };
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleAction(index) {
|
|
||||||
return { type: ActionTypes.TOGGLE_ACTION, index };
|
|
||||||
},
|
|
||||||
|
|
||||||
jumpToState(index) {
|
|
||||||
return { type: ActionTypes.JUMP_TO_STATE, index };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redux DevTools store enhancer.
|
|
||||||
*/
|
|
||||||
export default function enhance(monitorReducer = () => null) {
|
|
||||||
return next => (reducer, initialState) => {
|
|
||||||
const wrapReducer = (r) => combineReducers({
|
|
||||||
devToolsState: createDevToolsStateReducer(r, initialState),
|
|
||||||
monitorState: monitorReducer
|
|
||||||
});
|
|
||||||
|
|
||||||
const devToolsStore = next(wrapReducer(reducer));
|
|
||||||
return mapToComputedStateStore(devToolsStore, wrapReducer);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,51 +1,34 @@
|
||||||
export default function persistState(sessionId, stateDeserializer = null, actionDeserializer = null) {
|
const identity = _ => _;
|
||||||
|
export default function persistState(sessionId, deserializeState = identity, deserializeAction = identity) {
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
return next => (...args) => next(...args);
|
return next => (...args) => next(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deserializeState(fullState) {
|
function deserialize({ historyState, ...rest }) {
|
||||||
return {
|
return {
|
||||||
...fullState,
|
...rest,
|
||||||
committedState: stateDeserializer(fullState.committedState),
|
historyState: {
|
||||||
computedStates: fullState.computedStates.map((computedState) => {
|
...historyState,
|
||||||
return {
|
stagedActions: historyState.stagedActions.map(deserializeAction),
|
||||||
|
committedState: deserializeState(historyState.committedState),
|
||||||
|
computedStates: historyState.computedStates.map(computedState => ({
|
||||||
...computedState,
|
...computedState,
|
||||||
state: stateDeserializer(computedState.state)
|
state: deserializeState(computedState.state)
|
||||||
};
|
}))
|
||||||
})
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function deserializeActions(fullState) {
|
|
||||||
return {
|
|
||||||
...fullState,
|
|
||||||
stagedActions: fullState.stagedActions.map((action) => {
|
|
||||||
return actionDeserializer(action);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function deserialize(fullState) {
|
|
||||||
if (!fullState) {
|
|
||||||
return fullState;
|
|
||||||
}
|
|
||||||
let deserializedState = fullState;
|
|
||||||
if (typeof stateDeserializer === 'function') {
|
|
||||||
deserializedState = deserializeState(deserializedState);
|
|
||||||
}
|
|
||||||
if (typeof actionDeserializer === 'function') {
|
|
||||||
deserializedState = deserializeActions(deserializedState);
|
|
||||||
}
|
|
||||||
return deserializedState;
|
|
||||||
}
|
|
||||||
|
|
||||||
return next => (reducer, initialState) => {
|
return next => (reducer, initialState) => {
|
||||||
const key = `redux-dev-session-${sessionId}`;
|
const key = `redux-dev-session-${sessionId}`;
|
||||||
|
|
||||||
let finalInitialState;
|
let finalInitialState;
|
||||||
try {
|
try {
|
||||||
finalInitialState = deserialize(JSON.parse(localStorage.getItem(key))) || initialState;
|
const json = localStorage.getItem(key);
|
||||||
next(reducer, initialState);
|
if (json) {
|
||||||
|
finalInitialState = deserialize(JSON.parse(json)) || initialState;
|
||||||
|
next(reducer, initialState);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Could not read debug session from localStorage:', e);
|
console.warn('Could not read debug session from localStorage:', e);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import expect, { spyOn } from 'expect';
|
import expect, { spyOn } from 'expect';
|
||||||
import { createStore } from 'redux';
|
import { createStore } from 'redux';
|
||||||
import devTools, { ActionCreators } from '../src/devTools';
|
import instrument, { ActionCreators } from '../src/instrument';
|
||||||
|
|
||||||
function counter(state = 0, action) {
|
function counter(state = 0, action) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
@ -27,13 +27,13 @@ function doubleCounter(state = 0, action) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('devTools', () => {
|
describe('instrument', () => {
|
||||||
let store;
|
let store;
|
||||||
let devToolsStore;
|
let instrumentedStore;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
store = devTools()(createStore)(counter);
|
store = instrument()(createStore)(counter);
|
||||||
devToolsStore = store.devToolsStore;
|
instrumentedStore = store.instrumentedStore;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should perform actions', () => {
|
it('should perform actions', () => {
|
||||||
|
@ -49,20 +49,20 @@ describe('devTools', () => {
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.commit());
|
instrumentedStore.dispatch(ActionCreators.commit());
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(4);
|
expect(store.getState()).toBe(4);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.rollback());
|
instrumentedStore.dispatch(ActionCreators.rollback());
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
store.dispatch({ type: 'DECREMENT' });
|
store.dispatch({ type: 'DECREMENT' });
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.rollback());
|
instrumentedStore.dispatch(ActionCreators.rollback());
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -70,19 +70,19 @@ describe('devTools', () => {
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.commit());
|
instrumentedStore.dispatch(ActionCreators.commit());
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.rollback());
|
instrumentedStore.dispatch(ActionCreators.rollback());
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.reset());
|
instrumentedStore.dispatch(ActionCreators.reset());
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -93,10 +93,10 @@ describe('devTools', () => {
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.toggleAction(2));
|
instrumentedStore.dispatch(ActionCreators.toggleAction(2));
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.toggleAction(2));
|
instrumentedStore.dispatch(ActionCreators.toggleAction(2));
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -108,16 +108,16 @@ describe('devTools', () => {
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.toggleAction(2));
|
instrumentedStore.dispatch(ActionCreators.toggleAction(2));
|
||||||
expect(store.getState()).toBe(3);
|
expect(store.getState()).toBe(3);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.sweep());
|
instrumentedStore.dispatch(ActionCreators.sweep());
|
||||||
expect(store.getState()).toBe(3);
|
expect(store.getState()).toBe(3);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.toggleAction(2));
|
instrumentedStore.dispatch(ActionCreators.toggleAction(2));
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.sweep());
|
instrumentedStore.dispatch(ActionCreators.sweep());
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -127,19 +127,19 @@ describe('devTools', () => {
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.jumpToState(0));
|
instrumentedStore.dispatch(ActionCreators.jumpToState(0));
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.jumpToState(1));
|
instrumentedStore.dispatch(ActionCreators.jumpToState(1));
|
||||||
expect(store.getState()).toBe(1);
|
expect(store.getState()).toBe(1);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.jumpToState(2));
|
instrumentedStore.dispatch(ActionCreators.jumpToState(2));
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
store.dispatch({ type: 'INCREMENT' });
|
store.dispatch({ type: 'INCREMENT' });
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
devToolsStore.dispatch(ActionCreators.jumpToState(4));
|
instrumentedStore.dispatch(ActionCreators.jumpToState(4));
|
||||||
expect(store.getState()).toBe(2);
|
expect(store.getState()).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -155,17 +155,17 @@ describe('devTools', () => {
|
||||||
|
|
||||||
it('should catch and record errors', () => {
|
it('should catch and record errors', () => {
|
||||||
let spy = spyOn(console, 'error');
|
let spy = spyOn(console, 'error');
|
||||||
let storeWithBug = devTools()(createStore)(counterWithBug);
|
let storeWithBug = instrument()(createStore)(counterWithBug);
|
||||||
|
|
||||||
storeWithBug.dispatch({ type: 'INCREMENT' });
|
storeWithBug.dispatch({ type: 'INCREMENT' });
|
||||||
storeWithBug.dispatch({ type: 'DECREMENT' });
|
storeWithBug.dispatch({ type: 'DECREMENT' });
|
||||||
storeWithBug.dispatch({ type: 'INCREMENT' });
|
storeWithBug.dispatch({ type: 'INCREMENT' });
|
||||||
|
|
||||||
let devStoreState = storeWithBug.devToolsStore.getState();
|
let historyState = storeWithBug.instrumentedStore.getState().historyState;
|
||||||
expect(devStoreState.computedStates[2].error).toMatch(
|
expect(historyState.computedStates[2].error).toMatch(
|
||||||
/ReferenceError/
|
/ReferenceError/
|
||||||
);
|
);
|
||||||
expect(devStoreState.computedStates[3].error).toMatch(
|
expect(historyState.computedStates[3].error).toMatch(
|
||||||
/Interrupted by an error up the chain/
|
/Interrupted by an error up the chain/
|
||||||
);
|
);
|
||||||
expect(spy.calls[0].arguments[0]).toMatch(
|
expect(spy.calls[0].arguments[0]).toMatch(
|
||||||
|
@ -176,7 +176,7 @@ describe('devTools', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the last non-undefined state from getState', () => {
|
it('should return the last non-undefined state from getState', () => {
|
||||||
let storeWithBug = devTools()(createStore)(counterWithBug);
|
let storeWithBug = instrument()(createStore)(counterWithBug);
|
||||||
storeWithBug.dispatch({ type: 'INCREMENT' });
|
storeWithBug.dispatch({ type: 'INCREMENT' });
|
||||||
storeWithBug.dispatch({ type: 'INCREMENT' });
|
storeWithBug.dispatch({ type: 'INCREMENT' });
|
||||||
expect(storeWithBug.getState()).toBe(2);
|
expect(storeWithBug.getState()).toBe(2);
|
||||||
|
@ -187,7 +187,7 @@ describe('devTools', () => {
|
||||||
|
|
||||||
it('should not recompute states on every action', () => {
|
it('should not recompute states on every action', () => {
|
||||||
let reducerCalls = 0;
|
let reducerCalls = 0;
|
||||||
let monitoredStore = devTools()(createStore)(() => reducerCalls++);
|
let monitoredStore = instrument()(createStore)(() => reducerCalls++);
|
||||||
expect(reducerCalls).toBe(1);
|
expect(reducerCalls).toBe(1);
|
||||||
monitoredStore.dispatch({ type: 'INCREMENT' });
|
monitoredStore.dispatch({ type: 'INCREMENT' });
|
||||||
monitoredStore.dispatch({ type: 'INCREMENT' });
|
monitoredStore.dispatch({ type: 'INCREMENT' });
|
||||||
|
@ -197,8 +197,8 @@ describe('devTools', () => {
|
||||||
|
|
||||||
it('should not recompute states when jumping to state', () => {
|
it('should not recompute states when jumping to state', () => {
|
||||||
let reducerCalls = 0;
|
let reducerCalls = 0;
|
||||||
let monitoredStore = devTools()(createStore)(() => reducerCalls++);
|
let monitoredStore = instrument()(createStore)(() => reducerCalls++);
|
||||||
let monitoredDevToolsStore = monitoredStore.devToolsStore;
|
let monitoredInstrumentedStore = monitoredStore.instrumentedStore;
|
||||||
|
|
||||||
expect(reducerCalls).toBe(1);
|
expect(reducerCalls).toBe(1);
|
||||||
monitoredStore.dispatch({ type: 'INCREMENT' });
|
monitoredStore.dispatch({ type: 'INCREMENT' });
|
||||||
|
@ -206,13 +206,13 @@ describe('devTools', () => {
|
||||||
monitoredStore.dispatch({ type: 'INCREMENT' });
|
monitoredStore.dispatch({ type: 'INCREMENT' });
|
||||||
expect(reducerCalls).toBe(4);
|
expect(reducerCalls).toBe(4);
|
||||||
|
|
||||||
monitoredDevToolsStore.dispatch(ActionCreators.jumpToState(0));
|
monitoredInstrumentedStore.dispatch(ActionCreators.jumpToState(0));
|
||||||
expect(reducerCalls).toBe(4);
|
expect(reducerCalls).toBe(4);
|
||||||
|
|
||||||
monitoredDevToolsStore.dispatch(ActionCreators.jumpToState(1));
|
monitoredInstrumentedStore.dispatch(ActionCreators.jumpToState(1));
|
||||||
expect(reducerCalls).toBe(4);
|
expect(reducerCalls).toBe(4);
|
||||||
|
|
||||||
monitoredDevToolsStore.dispatch(ActionCreators.jumpToState(3));
|
monitoredInstrumentedStore.dispatch(ActionCreators.jumpToState(3));
|
||||||
expect(reducerCalls).toBe(4);
|
expect(reducerCalls).toBe(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,6 +1,5 @@
|
||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
import devTools from '../src/devTools';
|
import { instrument, persistState } from '../src';
|
||||||
import persistState from '../src/persistState';
|
|
||||||
import { compose, createStore } from 'redux';
|
import { compose, createStore } from 'redux';
|
||||||
|
|
||||||
describe('persistState', () => {
|
describe('persistState', () => {
|
||||||
|
@ -40,7 +39,7 @@ describe('persistState', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should persist state', () => {
|
it('should persist state', () => {
|
||||||
const finalCreateStore = compose(devTools(), persistState('id'))(createStore);
|
const finalCreateStore = compose(instrument(), persistState('id'))(createStore);
|
||||||
const store = finalCreateStore(reducer);
|
const store = finalCreateStore(reducer);
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ describe('persistState', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not persist state if no session id', () => {
|
it('should not persist state if no session id', () => {
|
||||||
const finalCreateStore = compose(devTools(), persistState())(createStore);
|
const finalCreateStore = compose(instrument(), persistState())(createStore);
|
||||||
const store = finalCreateStore(reducer);
|
const store = finalCreateStore(reducer);
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ describe('persistState', () => {
|
||||||
|
|
||||||
it('should run with a custom state deserializer', () => {
|
it('should run with a custom state deserializer', () => {
|
||||||
const oneLess = state => state === undefined ? -1 : state - 1;
|
const oneLess = state => state === undefined ? -1 : state - 1;
|
||||||
const finalCreateStore = compose(devTools(), persistState('id', oneLess))(createStore);
|
const finalCreateStore = compose(instrument(), persistState('id', oneLess))(createStore);
|
||||||
const store = finalCreateStore(reducer);
|
const store = finalCreateStore(reducer);
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
|
@ -81,7 +80,7 @@ describe('persistState', () => {
|
||||||
|
|
||||||
it('should run with a custom action deserializer', () => {
|
it('should run with a custom action deserializer', () => {
|
||||||
const incToDec = action => action.type === 'INCREMENT' ? { type: 'DECREMENT' } : action;
|
const incToDec = action => action.type === 'INCREMENT' ? { type: 'DECREMENT' } : action;
|
||||||
const finalCreateStore = compose(devTools(), persistState('id', null, incToDec))(createStore);
|
const finalCreateStore = compose(instrument(), persistState('id', undefined, incToDec))(createStore);
|
||||||
const store = finalCreateStore(reducer);
|
const store = finalCreateStore(reducer);
|
||||||
expect(store.getState()).toBe(0);
|
expect(store.getState()).toBe(0);
|
||||||
|
|
||||||
|
@ -95,7 +94,7 @@ describe('persistState', () => {
|
||||||
|
|
||||||
it('should warn if read from localStorage fails', () => {
|
it('should warn if read from localStorage fails', () => {
|
||||||
const spy = expect.spyOn(console, 'warn');
|
const spy = expect.spyOn(console, 'warn');
|
||||||
const finalCreateStore = compose(devTools(), persistState('id'))(createStore);
|
const finalCreateStore = compose(instrument(), persistState('id'))(createStore);
|
||||||
delete global.localStorage.getItem;
|
delete global.localStorage.getItem;
|
||||||
finalCreateStore(reducer);
|
finalCreateStore(reducer);
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ describe('persistState', () => {
|
||||||
});
|
});
|
||||||
it('should warn if write to localStorage fails', () => {
|
it('should warn if write to localStorage fails', () => {
|
||||||
const spy = expect.spyOn(console, 'warn');
|
const spy = expect.spyOn(console, 'warn');
|
||||||
const finalCreateStore = compose(devTools(), persistState('id'))(createStore);
|
const finalCreateStore = compose(instrument(), persistState('id'))(createStore);
|
||||||
delete global.localStorage.setItem;
|
delete global.localStorage.setItem;
|
||||||
const store = finalCreateStore(reducer);
|
const store = finalCreateStore(reducer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user