Testing ngrx meta reducers

Viewed 595

I have a meta reducer that should clear the state when logging out.

export function clearState(reducer: ActionReducer<any>): ActionReducer<any> {
  return (state, action) => {
    if (action.type === AuthActionTypes.UNAUTHENTICATED) {
      state = undefined;
    }
    return reducer(state, action);
  };
}

export const metaReducers: MetaReducer<any>[] = [clearState];

I want to unit test this piece of code. I have tested normal reducers before but for me it is hard to apply the same technique when writing a test for the meta reducer. And there are no examples in the docs.

2 Answers

I figured out a way to test it after digging deep in the ngrx source code

const invokeActionReducer = (currentState, action: any) => {
  return clearState((state) => state)(currentState, action);
};

it('should set state to initial value when logout action is dispatched', () => {
  const currentState = { /* state here */ };

  expect(invokeActionReducer(currentState, userUnauthenticated)).toBeFalsy();
});

Source

This might not be all of it but something like this should work:

let store: Store<any>;
....
store = TestBed.inject(Store); // TestBed.inject is TestBed.get in older versions of Angular
TestBed.configureTEstingModule({
  imports: [StoreModule.forRoot(/* put your reducers here */, { metaReducers })],
});

it('should re-initialize the state once unauthenticated is dispatched', async () => {
   store.dispatch(/* dispatch an action that will change the store */);
   const newPieceOfState = await this.store.select(state => ...).pipe(take(1)).toPromise(); // ensure the change took place
   expect(newPieceOfState).toEqual(...);
   store.dispatch(/* dispatch UNAUTHENTICATED */);
   const state = await this.store.select(state => ....).pipe(take(1)).toPromise();
   expect(state).toEqual(...); // do your assertions that the meta reducer took effect and the state changed
});
Related