Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is ngrx effect with filter valid?

Example:

myAwesomeEffect$ = createEffect(() =>
    this.actions$.pipe(
        ofType(MyAwesomeAction),
        concatMap(action => of(action).pipe(
            withLatestFrom(this.store$.pipe(select(myAwesomeSelector)))
        )),
        filter(([, myAwesomeValue]) => myAwesomeValue),
        map(() => myNotThatAwesomeAction())
    )
);

Few things to point out. As you can see the effect returns action only if the filter logic evaluates to true. That means the effect sometimes returns an action, sometimes it doesn't.

Is it a valid effect? Should I refrain from using filter operator in effect and replace it with if and a Noop action instead?

myAwesomeEffect$ = createEffect(() =>
    this.actions$.pipe(
        ofType(MyAwesomeAction),
        concatMap(action =>
            of(action).pipe(
                withLatestFrom(
                    this.store$.pipe(select(myAwesomeSelector))
                )
            )
        ),
        map(([, myAwesomeValue]) => {
            if (myAwesomeValue) {
                return myNotThatAwesomeAction();
            }
            return NoopAction();
        })
    )
);

The second example is easy to test:

it('should return myNotThatAwesomeAction when myAwesomeValue is true', done => {
    store.overrideSelector(myAwesomeSelector, true);
    myAwesomeEffect$().subscribe(res => {
        expect(res).toEqual(myNotThatAwesomeAction());
        done();
    });
});

it('should return NoopAction when myNotThatAwesomeAction is false', () => {
    store.overrideSelector(myAwesomeSelector, false);
    myAwesomeEffect$().subscribe(res => {
        expect(res).toEqual(NoopAction());
        done();
    });
});

But what about the first example.

it('should return myNotThatAwesomeAction when myAwesomeValue is true', done => {
    store.overrideSelector(myAwesomeSelector, true);
    myAwesomeEffect$().subscribe(res => {
        expect(res).toEqual(myNotThatAwesomeAction());
        done();
    });
});

it('should not return myNotThatAwesomeAction when myNotThatAwesomeAction is false', done => {
    store.overrideSelector(myAwesomeSelector, false);
    // This won't work since the effect won't return anything

    myAwesomeEffect$().subscribe(res => {
        expect(res).not.toEqual(myNotThatAwesomeAction());
        done();
    });
});

What should I replace the second test case with? (while not using third party libs)

Update:

To test an effect which contains filter operator I choose this way:

it('myAwesomeEffect$ does not return anything when myAwesomeValue is false', done => {
    myEffects.myAwesomeEffect$.subscribe(
        () => done.fail(),
        () => done.fail(),
        () => {
            expect(true).toBeTruthy();
            done();
        }
    );

});

So if it throws, error or if it produces value we fail the test.

like image 325
gr4viton Avatar asked Jan 22 '26 08:01

gr4viton


1 Answers

Using the filter operator to "stop" the effect stream is valid.

like image 149
timdeschryver Avatar answered Jan 25 '26 02:01

timdeschryver



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!