From 51a1547fb3d8f0d7c7db8e8e1a9b7d5e842ca970 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Sat, 3 Mar 2018 06:58:24 -0800 Subject: [PATCH] fix(Store): only default to initialValue when store value is undefined (#886) --- modules/store/spec/store.spec.ts | 70 ++++++++++++++++++++++++++++ modules/store/src/reducer_manager.ts | 2 +- modules/store/src/utils.ts | 2 +- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/modules/store/spec/store.spec.ts b/modules/store/spec/store.spec.ts index 808c112944..a35a4e5dee 100644 --- a/modules/store/spec/store.spec.ts +++ b/modules/store/spec/store.spec.ts @@ -68,6 +68,76 @@ describe('ngRx Store', () => { complete: done, }); }); + + function testInitialState(feature?: string) { + store = TestBed.get(Store); + dispatcher = TestBed.get(ActionsSubject); + + const actionSequence = '--a--b--c--d--e--f--g'; + const stateSequence = 'i-w-----x-----y--z---'; + const actionValues = { + a: { type: INCREMENT }, + b: { type: 'OTHER' }, + c: { type: RESET }, + d: { type: 'OTHER' }, //reproduces https://github.com/ngrx/platform/issues/880 because state is falsey + e: { type: INCREMENT }, + f: { type: INCREMENT }, + g: { type: 'OTHER' }, + }; + const counterSteps = hot(actionSequence, actionValues); + counterSteps.subscribe(action => store.dispatch(action)); + + const counterStateWithString = feature + ? (store as any).select(feature, 'counter1') + : store.select('counter1'); + + const counter1Values = { i: 1, w: 2, x: 0, y: 1, z: 2 }; + + expect(counterStateWithString).toBeObservable( + hot(stateSequence, counter1Values) + ); + } + + it('should reset to initial state when undefined (root ActionReducerMap)', () => { + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot( + { counter1: counterReducer }, + { initialState: { counter1: 1 } } + ), + ], + }); + + testInitialState(); + }); + + it('should reset to initial state when undefined (feature ActionReducer)', () => { + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({}), + StoreModule.forFeature('counter1', counterReducer, { + initialState: 1, + }), + ], + }); + + testInitialState(); + }); + + it('should reset to initial state when undefined (feature ActionReducerMap)', () => { + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({}), + StoreModule.forFeature( + 'feature1', + { counter1: counterReducer }, + { initialState: { counter1: 1 } } + ), + ], + }); + + testInitialState('feature1'); + }); }); describe('basic store actions', () => { diff --git a/modules/store/src/reducer_manager.ts b/modules/store/src/reducer_manager.ts index 5274e5042b..025fc064a4 100644 --- a/modules/store/src/reducer_manager.ts +++ b/modules/store/src/reducer_manager.ts @@ -43,7 +43,7 @@ export class ReducerManager extends BehaviorSubject> typeof reducers === 'function' ? (state: any, action: any) => createFeatureReducer(reducers, metaReducers)( - state || initialState, + state === undefined ? initialState : state, action ) : createReducerFactory(reducerFactory, metaReducers)( diff --git a/modules/store/src/utils.ts b/modules/store/src/utils.ts index f29ba77a06..2364ffb983 100644 --- a/modules/store/src/utils.ts +++ b/modules/store/src/utils.ts @@ -27,7 +27,7 @@ export function combineReducers( const finalReducerKeys = Object.keys(finalReducers); return function combination(state, action) { - state = state || initialState; + state = state === undefined ? initialState : state; let hasChanged = false; const nextState: any = {}; for (let i = 0; i < finalReducerKeys.length; i++) {