0
votes

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.

1
This anotherObject is a service or simply an object that emits errors on the errorSource$ subject?NateScript
anotherObject is an Akita Query (state management query) that emits items from a store on change. datorama.github.io/akita/docs/queryzak
But I think the only thing what important is what errorSource$ emits, right?zak

1 Answers

1
votes

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.