Skip to content
This repository has been archived by the owner on Jan 3, 2025. It is now read-only.

Commit

Permalink
fix(Devtools): Filtered out all undefined states
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeRyanDev committed Mar 2, 2016
1 parent a1a5c91 commit 0f2c4ff
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 33 deletions.
30 changes: 15 additions & 15 deletions spec/store_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,18 @@ describe('instrument', () => {
store.dispatch({ type: 'INCREMENT' });

expect(store.getValue()).toBe(2);
expect(devtools.state$.getValue().stagedActionIds).toEqual([0, 1, 2, 3, 4]);
expect(devtools.state$.getValue().skippedActionIds).toEqual([]);
expect(devtools.getValue().stagedActionIds).toEqual([0, 1, 2, 3, 4]);
expect(devtools.getValue().skippedActionIds).toEqual([]);

devtools.dispatch(StoreDevtoolActions.toggleAction(2));
expect(store.getValue()).toBe(3);
expect(devtools.state$.getValue().stagedActionIds).toEqual([0, 1, 2, 3, 4]);
expect(devtools.state$.getValue().skippedActionIds).toEqual([2]);
expect(devtools.getValue().stagedActionIds).toEqual([0, 1, 2, 3, 4]);
expect(devtools.getValue().skippedActionIds).toEqual([2]);

devtools.dispatch(StoreDevtoolActions.sweep());
expect(store.getValue()).toBe(3);
expect(devtools.state$.getValue().stagedActionIds).toEqual([0, 1, 3, 4]);
expect(devtools.state$.getValue().skippedActionIds).toEqual([]);
expect(devtools.getValue().stagedActionIds).toEqual([0, 1, 3, 4]);
expect(devtools.getValue().skippedActionIds).toEqual([]);
});

it('should jump to state', () => {
Expand Down Expand Up @@ -193,7 +193,7 @@ describe('instrument', () => {
store.dispatch({ type: 'DECREMENT' });
store.dispatch({ type: 'INCREMENT' });

let { computedStates } = devtools.state$.getValue();
let { computedStates } = devtools.getValue();
expect(computedStates[2].error).toMatch(
/ReferenceError/
);
Expand All @@ -213,7 +213,7 @@ describe('instrument', () => {
);
});

xit('should return the last non-undefined state from getValue', () => {
it('should return the last non-undefined state from getValue', () => {
let { store } = createStore(counterWithBug);
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'INCREMENT' });
Expand Down Expand Up @@ -277,7 +277,7 @@ describe('instrument', () => {
store.dispatch({ type: 'INCREMENT' });
expect(reducerCalls).toBe(4);

let savedComputedStates = devtools.state$.getValue().computedStates;
let savedComputedStates = devtools.getValue().computedStates;

devtools.dispatch(StoreDevtoolActions.jumpToState(0));
expect(reducerCalls).toBe(4);
Expand All @@ -288,7 +288,7 @@ describe('instrument', () => {
devtools.dispatch(StoreDevtoolActions.jumpToState(3));
expect(reducerCalls).toBe(4);

expect(devtools.state$.getValue().computedStates).toBe(savedComputedStates);
expect(devtools.getValue().computedStates).toBe(savedComputedStates);
});

it('should not recompute states on monitor actions', () => {
Expand All @@ -302,15 +302,15 @@ describe('instrument', () => {
store.dispatch({ type: 'INCREMENT' });
expect(reducerCalls).toBe(4);

let savedComputedStates = devtools.state$.getValue().computedStates;
let savedComputedStates = devtools.getValue().computedStates;

devtools.dispatch({ type: 'lol' });
expect(reducerCalls).toBe(4);

devtools.dispatch({ type: 'wat' });
expect(reducerCalls).toBe(4);

expect(devtools.state$.getValue().computedStates).toBe(savedComputedStates);
expect(devtools.getValue().computedStates).toBe(savedComputedStates);
});

describe('Import State', () => {
Expand All @@ -321,14 +321,14 @@ describe('instrument', () => {
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'INCREMENT' });

exportedState = devtools.state$.getValue();
exportedState = devtools.getValue();
});

it('should replay all the steps when a state is imported', () => {
let {store, devtools} = createStore(counter);

devtools.dispatch(StoreDevtoolActions.importState(exportedState));
expect(devtools.state$.getValue()).toEqual(exportedState);
expect(devtools.getValue()).toEqual(exportedState);
});

it('should replace the existing action log with the one imported', () => {
Expand All @@ -338,7 +338,7 @@ describe('instrument', () => {
store.dispatch({ type: 'DECREMENT' });

devtools.dispatch(StoreDevtoolActions.importState(exportedState));
expect(devtools.state$.getValue()).toEqual(exportedState);
expect(devtools.getValue()).toEqual(exportedState);
});
});
});
55 changes: 37 additions & 18 deletions src/store/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,57 @@ import 'rxjs/add/operator/let';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/merge';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';

import {Dispatcher, Middleware, Reducer} from '@ngrx/store';
import {ActionTypes} from '@ngrx/store/dist/store-backend';
import {liftAction, unliftState, liftReducerWith, WrappedState} from './instrument';

export class StoreDevtools {
protected _reducer: Reducer<WrappedState>;
protected _initialLiftedState: WrappedState;
dispatcher$ = new Dispatcher<any>();
state$: BehaviorSubject<WrappedState>;
export class StoreDevtools extends BehaviorSubject<WrappedState> {
private _reducer: Reducer<WrappedState>;
private _initialLiftedState: WrappedState;
private _liftedDispatcher: Dispatcher<any>;
private _initialState: any;
private _preMiddleware: Middleware;
private _postMiddleware: Middleware;
private _monitorReducer: any;
private _dispatcher: Dispatcher<any>;

constructor(
_reducer: Reducer<any>,
protected _dispatcher: Dispatcher<any>,
protected _initialState: any,
protected _preMiddleware: Middleware = t => t,
protected _postMiddleware: Middleware = t => t,
protected _monitorReducer: any
_dispatcher: Dispatcher<any>,
_initialState: any,
_preMiddleware: Middleware,
_postMiddleware: Middleware,
_monitorReducer: any
) {
this._reducer = liftReducerWith(_reducer, _initialState, _monitorReducer);
this._initialLiftedState = this._reducer(undefined, { type: ActionTypes.INIT });
this.state$ = new BehaviorSubject(this._initialLiftedState);
const reducer = liftReducerWith(_reducer, _initialState, _monitorReducer);
const initialLiftedState = reducer(undefined, { type: ActionTypes.INIT });

super(initialLiftedState);

this._reducer = reducer;
this._initialLiftedState = initialLiftedState;
this._liftedDispatcher = _dispatcher;
this._preMiddleware = _preMiddleware;
this._postMiddleware = _postMiddleware;
this._monitorReducer = _monitorReducer;
this._dispatcher = new Dispatcher<any>();
}

protected _init() {
private _init() {
this.dispatch({ type: ActionTypes.INIT });
}

connect(nextCallbackFn: (state: any) => void) {
this._dispatcher
this._liftedDispatcher
.let(this._preMiddleware)
.map(liftAction)
.merge(this.dispatcher$)
.merge(this._dispatcher)
.scan((state: WrappedState, action) => this._reducer(state, action), this._initialLiftedState)
.do((liftedState: WrappedState) => this.state$.next(liftedState))
.do((liftedState: WrappedState) => super.next(liftedState))
.map(unliftState)
.filter(state => state !== undefined)
.let(this._postMiddleware)
.subscribe(nextCallbackFn);

Expand All @@ -53,6 +68,10 @@ export class StoreDevtools {
}

dispatch(action){
this.dispatcher$.next(action);
this._dispatcher.next(action);
}

next(action: any){
this._dispatcher.next(action);
}
}

0 comments on commit 0f2c4ff

Please sign in to comment.