jeudi 29 novembre 2018

Unit testing a component which has a promise which contains an Observable

I am having a problem unit testing some functionality in a component were a function is called which returns a promise and that promise itself contains an observable subscription.

I have mocked the Observable response but I am unsure as to how I get this working correctly.

Here is the component functions in question:

public addAncillary(ancillaryCode: AncillaryCode): void {
    this.ancillariesArray.push(ancillaryCode);

    // This code is to be refactored to remove this logic call the ancillary service to calculate quote price
    if (ancillaryCode === AncillaryCode.BuildingsAD || ancillaryCode === AncillaryCode.ContentsAD) {
      this.getRequote(this.selectedTier)
        .then((price: number) => {
          this.adjustedCurrentTierPrice = (price + this.generatePriceWithAncills());
          this.redrawTable();
        });
    } else {
      let ancillary = this.selectedTier.ancillaries.find(ancillary => ancillary.code === ancillaryCode);
      this.adjustedCurrentTierPrice += ancillary.price + ancillary.taxAmount;
    }

    this.rows = this.getRows();
  }

As you can see, the above function contains the call to the function which returns a promise.

public getRequote(tier): Promise<number> {
    return new Promise((resolve, reject) => {
      this.Modal.load('loading', true);
      const quotePayload: Quote = {
        ...this.quoteRequest,
        quoteNumber: this.quoteResponse.quoteResponse.quoteRetrieval.quoteNumber,
        quoteVersion: this.quoteResponse.quoteResponse.quoteRetrieval.quoteVersion,
      };

      this.quoteService.getRequote(quotePayload, [...this.ancillariesArray], this.selectedTier)
        .subscribe((response) => {
          this.Modal.close('loading', true);
          this.quoteResponseStore.change(response);

          // remove this.quoteResponse to use this.quoteResponse.get()
          this.quoteResponse = response;
          const selectedTierQuote = response.quoteResponse.homeInsuranceQuote.home[0].tiers.find((tierIteration) => {
            return tier.name === tierIteration.name;
          });

          resolve(selectedTierQuote.annualPremium.total);
        });
    });
  }

And as you can see here, this function returns the promise which itself resolves after the observable has been subscribed too.

Here is my attempt at testing this:

fit('Should call call the Quote Service Requote method and update premium when AD is given to addAncillary method', fakeAsync(() => {
        const quoteServiceMock = TestBed.get(QuoteService);
        const modalServiceMock = TestBed.get('Modal');

        let quoteServiceSpy, addAncillarySpy, modalLoadingSpy;

        quoteServiceSpy = spyOn(quoteServiceMock, 'getRequote').and.callThrough();
        addAncillarySpy = spyOn(component, "addAncillary").and.callThrough();
        modalLoadingSpy = spyOn(modalServiceMock, 'load').and.callThrough();

        component.addAncillary(AncillaryCode.BuildingsAD);
        flush();

        fixture.whenStable()
            .then(() => {
              expect(addAncillarySpy).toHaveBeenCalledWith(AncillaryCode.BuildingsAD);
              expect(modalLoadingSpy).toHaveBeenCalled();
              expect(quoteServiceSpy).toHaveBeenCalled();

              expect(component.adjustedCurrentTierPrice).toEqual(132.55);

              fixture.detectChanges();
              expect(fixture.nativeElement.querySelector('#total-premium').textContent).toEqual(' £132.55 ');
            });
      }));

Can anyone see what I am going wrong here? The test itself is not working as expected at the price that is tested at the bottom is not being updated from the mocked service. I have mocked the quote service in the test too so real http calls aren't happening.

Thanks

Aucun commentaire:

Enregistrer un commentaire