jest-marbles icon indicating copy to clipboard operation
jest-marbles copied to clipboard

toObservable followed by toSatisfyOnFlush created double calls.

Open rainoko opened this issue 2 years ago • 5 comments

  describe('toSatisfyOnFlush', () => {
    it('should verify mock has been called', () => {
      const mock = jest.fn();
      const coldObservable = cold('blah|');
      const stream$ = coldObservable.pipe(tap(mock));
      expect(stream$).toBeObservable(coldObservable);
      expect(stream$).toSatisfyOnFlush(() => {
        expect(mock).toHaveBeenCalledTimes(4);
      });
    });
  });

This test fails with call times actually 8 not 4. Even though it technically can be understandable, is is not intuitive when reading the test.

workaround is to separate this into 2 separate tests.

rainoko avatar Oct 25 '21 09:10 rainoko

What I did was to put the toBeObservable Code inside the toSatisfyOnFlush block. But I agree, it is counterintuitive.

      expect(stream$).toSatisfyOnFlush(() => {
          expect(stream$).toBeObservable(coldObservable);
          expect(mock).toHaveBeenCalledTimes(4);
      });

Blafasel3 avatar Jun 29 '22 06:06 Blafasel3

Hi! Is there any specific reason for not having the flush logic directly implemented within the toBeObservable() like jasmine-marbles does? This would be super helpful 😅

despeekapool avatar Jun 30 '22 15:06 despeekapool

I came here for the same problem, I followed your suggestion @Blafasel3, but when inside the toSatisfyOnFlush(), the expect().toBeObservable() always pass, whatever the coldObservable I'm testing...

For instance, this fails as expected, but triggers the observable several times :

    const stream$ = hot('a', { a: myAction(payload) });
    const coldObservable = cold('b', { b: undefined });

    expect(stream$).toBeObservable(coldObservable);
    expect(stream$).toSatisfyOnFlush(() => {
      expect(mock).toHaveBeenCalledTimes(4);
    });

But this pass while it shouldn't:

    const stream$ = hot('a', { a: myAction(payload) });
    const coldObservable = cold('b', { b: undefined });

    expect(stream$).toSatisfyOnFlush(() => {
      expect(stream$).toBeObservable(coldObservable);
      expect(mock).toHaveBeenCalledTimes(4);
    });

I have other asserts in the toSatisfyOnFlush that fail when I change them, so I don't understand why the expect doesn't fail... I'm using Jest 28.1.3 & jest-marbles 3.0.2

killergege avatar Jun 16 '23 10:06 killergege

@killergege Interesting, I'll take a look.

just-jeb avatar Jun 21 '23 10:06 just-jeb

I came here for the same problem, I followed your suggestion @Blafasel3, but when inside the toSatisfyOnFlush(), the expect().toBeObservable() always pass, whatever the coldObservable I'm testing...

For instance, this fails as expected, but triggers the observable several times :

    const stream$ = hot('a', { a: myAction(payload) });
    const coldObservable = cold('b', { b: undefined });

    expect(stream$).toBeObservable(coldObservable);
    expect(stream$).toSatisfyOnFlush(() => {
      expect(mock).toHaveBeenCalledTimes(4);
    });

But this pass while it shouldn't:

    const stream$ = hot('a', { a: myAction(payload) });
    const coldObservable = cold('b', { b: undefined });

    expect(stream$).toSatisfyOnFlush(() => {
      expect(stream$).toBeObservable(coldObservable);
      expect(mock).toHaveBeenCalledTimes(4);
    });

I have other asserts in the toSatisfyOnFlush that fail when I change them, so I don't understand why the expect doesn't fail... I'm using Jest 28.1.3 & jest-marbles 3.0.2

Oh, I never actually tested that. Thanks for pointing that out!

Blafasel3 avatar Jun 21 '23 19:06 Blafasel3