1

Hi I am trying to write angular code for a component with an observable but I can't access the subscribe function. How Should I access the subscribe function to test the code within? Any help would be appreciated. Thank you.

This is my component with the observable:

  ngOnInit(): void {

    if (this.authService.getUser() !== null || this.authService.getUser() !== undefined) {
      this.userService.userDetails = this.authService.getUser();
    }

    if (this.environmentName === 'QA' || this.environmentName === 'LOCAL' || this.environmentName === 'QA-STAGING') {
      this.authService.acquireTokenSilent(['api://012fdc3a-c966-4312-9b5c-301f097c1803/server']);
    } else {
      this.authService.acquireTokenSilent(['api://58a80bb5-906b-4ec0-9b41-7a78a07125af/server']);
    }

    this.subscription.add(
      this.broadcastService.subscribe('msal:acquireTokenSuccess', (payload) => {
        console.log('acquire token success ' + JSON.stringify(payload));
        this.roleService.checkServerEventReviewers().subscribe(res => {
          this.userService.userDetails.role = res ? 'Data Steward' : 'Mosaic Consumer';
          if (this.isLoggedIn !== true) {
            const redirectUri = sessionStorage.getItem('redirectUri');
            if (redirectUri !== undefined || redirectUri !== null) {
              this.router.navigateByUrl(redirectUri);
            }
          }
          this.isLoggedIn = true;
};

This is my spec file that I am trying:

describe('AppComponent', () => {
  beforeEach(() => {
    let subscription: Subscription = new Subscription();
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
      providers: [WindowService, RoleService, HttpClient, HttpHandler, BroadcastService, MsalService,
        {
          provide: MSAL_CONFIG,  // MsalService needs config, this provides it.
          useFactory: () => ({   // Note this is an arrow fn that returns the config object
            redirectUri: window.location.origin + '/',
            clientID: mockData.clientID,
          }),
        }],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    }).compileComponents();
  });

  describe(':', () => {
    function setup() {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.debugElement.componentInstance;
      const compiled = fixture.debugElement.nativeElement;
      return {fixture, app, compiled};
    }

    it('Init with QA environment', () => {
      const {app} = setup();
      spyOn(app.authService, 'getUser').and.returnValue(mockData.userDetails);
      spyOn(app.authService, 'acquireTokenSilent').and.returnValue('msal:acquireTokenSuccess');
      app.ngOnInit();
      app.subscription.add(
        app.broadcastService.subscribe('msal:acquireTokenSuccess', () => {
        // do something here
        });
    );
Roh
  • 311
  • 1
  • 10

1 Answers1

0

There are two way to do it:

  1. You can extract the function and test it as a function itself

Declare it as follows:

 function handlePayload(payload) {
    console.log('acquire token success ' + JSON.stringify(payload));
    this.roleService.checkServerEventReviewers().subscribe(res => {
      this.userService.userDetails.role = res ? 'Data Steward' : 'Mosaic Consumer';
      if (this.isLoggedIn !== true) {
        const redirectUri = sessionStorage.getItem('redirectUri');
        if (redirectUri !== undefined || redirectUri !== null) {
          this.router.navigateByUrl(redirectUri);
        }
      }
      this.isLoggedIn = true;
}

and in ngOnInit

this.subscription.add(
  this.broadcastService.subscribe('msal:acquireTokenSuccess', this.handlePayload));

So now you can test the handle payload directly

  1. Mock this.broadcastService with a spy to return an observable with the of function.

This way you will test the outcome of the subscription by calling ngOnInit.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • Could you explain a little more about the second method. What would be the observable that I would return – Roh Nov 13 '19 at 17:08
  • What is the type of this.broadcastService? You need to do something like spyOn(app.broadcastService).and.return(`ExpectedType`); In all honesty, it would be much less of a hussle to go with option one as option two would require deep understanding of the types returned by the angular MSAL language to simulate. – Athanasios Kataras Nov 13 '19 at 17:15
  • Is it possible that I spy *roleService.checkServerEventReviewers()* without spying on broadcastService first? Also for the first method do I define the function in the component? – Roh Nov 13 '19 at 19:20
  • Its not working as there is a `.subscribe()` call in the function which is why I can not define it as a function – Roh Nov 13 '19 at 21:10