[Fixed] RxJs: Testing observable that depends on other observable/

Issue

I have an observable called isSearchEnabled$, that indicates whether the search button on search form is clickable or not.
This is the code for the observable:

isSearchEnabled$ = anotherObject.errorSource$.pipe(map((errors) => errors.length === 0);

As one can see, this observable is depending on another observable, which emits an array every time form validation occurs. So isSearchEnabled emits a boolean true when the array is empty, false otherwise.

I wanna test this observable, but I’m not sure how. I should mock anotherObject.errorSource$ to emit fake errors, and check whether isSearchEnabled$ returns true or false?

How should i do it in Angular/RxJS?
If somebody have solution in spectator, or just a regular solution, I’d really appreciate it!

PS.: I know I should provide a working example, but I think this description is quiet straightforward, and no need further code.

Solution

If anotherObject is an object as you specify above you could do something like this. AnotherObject Stackblitz

describe("HelloComponent", () => {
  let spectator: Spectator<HelloComponent>;

  const createComponent = createComponentFactory({
    component: HelloComponent,
    providers: [],
    detectChanges: false
  });

  beforeEach(() => {
    spectator = createComponent();
  });

  it("should be disabled", done => {
    const errors = [new Error("xyz"), new Error("abc")];
    spectator.component.anotherObject = { errorSource$: of(errors) };
    spectator.detectChanges();
    spectator.component.isSearchEnabled$.subscribe({
      next: isSearchEnabled => {
        expect(isSearchEnabled).toBeFalse();
       //You might want to test here whether your component template/state changed..
        done();
      }
    });
  });

  it("should be enabled", done => {
    spectator.component.anotherObject = { errorSource$: of([]) };
    spectator.detectChanges();
    spectator.component.isSearchEnabled$.subscribe({
      next: isSearchEnabled => {
        expect(isSearchEnabled).toBeTrue();
        done();
      }
    });
  });
});

If you get the observable from the akita query the best option is to mock the query method your observable is dependent on. I haven’t tested the code below, but something similar should work.

  let spectator: Spectator<HelloComponent>;
  let query: SpyObject<AkitaAnotherObjectQuery>;

  const createComponent = createComponentFactory({
    component: HelloComponent,
    mocks: [AkitaAnotherObjectQuery],
    detectChanges: false
  });

  beforeEach(() => {
    spectator = createComponent();
    query = spectator.inject(AkitaAnotherObjectQuery);
    //return empty array to check if search is enabled by default
    query.selectErrorSource.andReturn(of([]));
  });

  it('should be enabled', () => {
     spectator.detectChanges();
     //todo test whether component state changed..
  });

  //test could be fake async or if you want to test the observable you can subscribe to it in the test below
  it('should be disabled', () => {
    const errors = [new Error('myError')];
    query.selectErrorSource.andReturn(of(errors));
    spectator.detectChanges();
    //todo test whether component state changed..
   });

  ....

Hope it works out, let me know if you have any more questions. If you want I can also add an example of the akita query mock in Stackblitz, just let me know.

Leave a Reply

(*) Required, Your email will not be published