[Fixed] Variable always undefined with await Jasmine

Issue

I need to test a function, and in that function a variable is created and assigned a value.

But the payload constant is always undefined.

campaigns-card.component.ts

async ngOnInit() {
    const { uid } = await this.auth.currentUser
    const { payload } = await this.firestore.surveysUsers(this.survey.id).doc(uid).snapshotChanges().pipe(first()).toPromise();
    this.completed = payload.exists
  }

component-card.component.spec.ts

beforeEach(waitForAsync(() => {
    fireStoreServiceMock.surveysUsers.and.returnValue({ 
      doc: () => { return {
        snapshotChanges: () => { return {
          pipe: () => { return {
            toPromise: () => { return { exists: true }}
          }}
        }}
      }}
    });
  }));

describe('tests in delete', () => {
    it('should update surveys', fakeAsync(() => {
      fixture.detectChanges();
      component.delete().then(() => {
      });
      fixture.detectChanges();
      tick();

      expect(fireStoreServiceMock.surveys).toHaveBeenCalled();
      expect(snackBarMock.open).toHaveBeenCalled();
    }));
  });

error

Error: Uncaught (in promise): TypeError: Cannot read property 'exists' of undefined
TypeError: Cannot read property 'exists' of undefined
    at CampaignsCardComponent.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/modules/campaigns/pages/campaigns-card/campaigns-card.component.ts:43:4)
    at Generator.next (<anonymous>)
    at fulfilled (http://localhost:9876/_karma_webpack_/webpack:/node_modules/tslib/tslib.es6.js:71:42)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:372:1)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/proxy.js:126:1)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:371:1)
    at Object.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/fesm2015/core.js:28535:1)
    at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:371:1)
    at Zone.run (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:134:1)
    at http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:1276:1

Solution

Almost there. The issue is that this is an observable and you shouldn’t be mocking the pipe function on it but return an observable from the function call.

Try this:

import { of } from 'rxjs';
....
beforeEach(waitForAsync(() => {
    fireStoreServiceMock.surveysUsers.and.returnValue({ 
      doc: () => { return {
        snapshotChanges: () => of({ exists: true }) // mock the observable with of
        }}
      }}
    });
  }));

I may have messed up the brackets ({ }) with the changes but that should do it.

Leave a Reply

(*) Required, Your email will not be published