Home > Net >  Test is not entering rxjs operator pipe and tap in the Angular code
Test is not entering rxjs operator pipe and tap in the Angular code

Time:01-14

My test is not able to cover the pipe part of the code, don't know what's wrong. covereage of the code. I am using ngx-chip in the template. The autocompleteObservable picks the text typed in the tag-input and is passed it to the requestAutocompleteItems, further it is passed to peopleService to get data based on the text. There is also a spinner that is manually turned on and off before and after the data is processed.

component.html

<tag-input
  theme="foundation-theme"
  [placeholder]="placeholder"
  [secondaryPlaceholder]="secondPlaceholder"
  onlyFromAutocomplete="true"
  [animationDuration]="animation"
  [(ngModel)]="items"
  (onAdd)="onItemAdded($event)"
  (onRemove)="onItemRemoved()"
  [maxItems]="maxItems"
  (focusout)="stopLoading()"
>
  <tag-input-dropdown
    [autocompleteObservable]="requestAutocompleteItems"
    [dynamicUpdate]="false"
    [displayBy]="fieldName"
    [identifyBy]="fieldId"
    [minimumTextLength]="numberText"
    [appendToBody]="false"
  >
  </tag-input-dropdown>
</tag-input>
<div  *ngIf="showLoading">
  <p-progressSpinner></p-progressSpinner>
</div>

component.ts

ngOnInit() {
    this.requestAutocompleteItems = (text: string): Observable<AutoCompleteItem[]> => {
      this.showLoading = true;
      // Add this to an autocomplete
      let textJson;
      if (this.department) {
        textJson = {
          where: { and: [{ displayName: { like: text } }, { department: { like: this.department } }] },
          include: this.colsIncluded,
        };
      } else {
        textJson = { where: { displayName: { like: text } }, include: this.colsIncluded };
      }
      return this.peopleService.getData(JSON.stringify(textJson)).pipe(
        tap(() => {
          this.showLoading = false;
        }),
      );
    };
  }

component.spec.ts

it('should stop loading', () => {
    peoplePickerServiceSpy.getData.and.returnValue(of({}));
    fixture.detectChanges();
    component.requestAutocompleteItems('erv');
    fixture.detectChanges();
    expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
  });

CodePudding user response:

Your test is lacking subscription to the requestAutocompleteItems. If nothing subscribes to it the code in the tap operator will never fire. So you either provide a tag-input mock which is capable of doing that, or do it without it. And this is a good question for experts, whether we care about how is our observable treated in some child component, or we don't.

If you decide you don't worry about it, you should wrap your unit test to fakeAsync function and then subscribe to requestAutocompleteItems within UT.

it('should stop loading', fakeAsync(() => {
  peoplePickerServiceSpy.getData.and.returnValue(of({}));
  fixture.detectChanges();

  component.requestAutocompleteItems('erv').subscribe(() => {
    expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
  });
  fixture.detectChanges();

  tick(); //necessary -> simulates the asynchronous passage of time
}));

CodePudding user response:

This is how I fixed the issue just as Mat said it needs a subscribe block to complete the observable I added a done function.

it('should stop loading', done => {
    peoplePickerServiceSpy.getData.and.returnValue(of({}));
    fixture.detectChanges();
    component.requestAutocompleteItems('erv').subscribe(() => {
      expect(peoplePickerServiceSpy.getData).toHaveBeenCalled();
      done();
    });
  });
  •  Tags:  
  • Related