Search code examples
rxjsjestjsreactive-programmingredux-observablerxjs-marbles

How to write marble test for this custom RxJS operator used in redux-observalbe Epic


I need to write marble test for my custom operator used in this loadEpic epic - this helps me to avoid problems that action INITIALiZE sometimes is dispatched to late and i getting LOAD_FAILURE:

loadEpic: Epic<ExamManagementAction, ExamManagementAction, RootState> = (
    action$,
    state$
  ) =>
    action$.pipe(
      filter(isActionOf(load)),
      waitFor(state$),
      switchMap(() =>
        this.load(state$).pipe(
          map(loadSuccess),
          catchError(error => of(loadFailure({ error })))
        )
      )
    );

and this is how i wrote my waitFor operator which works fine:

const waitFor = <T>(
  state$: Observable<RootState>
): OperatorFunction<T, T> => source$ =>
  source$.pipe(
    switchMap(value =>
      state$.pipe(
        filter(state => state.navigation.initialized),
        take(1),
        mapTo(value)
      )
    )
  );

can you help me to write this test with rxjs-marbles/jest or any similar approach? many thanks!


Solution

  • You describe three streams of events:

    1. states (mock them with simple objects)
    2. actions (again, you may use any JS value as a mock)
    3. filtered actions (the same object as in 2)

    Then you expect your operator to transform 2 to 3 with toBeObservable matcher. That's it.

      it('should reject given values until navigation is initialized', () => {
        const state$ = hot('   -i--u--u-i--  ', {u: {navigation: {initialized: false}}, i: {navigation: {initialized: true}}});
        const action$ = hot('  v----v--v---  ', {v: load});
        const expect$ = cold(' -v-------v--  ', {v: load});
    
        expect(action$.pipe(waitFor(state$))).toBeObservable(expect$);
      });
    
    

    Note how I've formatted my code so one stream is described under another. It really helps with long sequences of events.

    You might also write separate specs for edge cases. It depends on what behavior you want to test.