How to test router.url in Angular/Jasmine app


ionic angular jasmine e2e

For example we have the following component in our Angular or Ionic application:

import { ChangeDetectionStrategy, Component } from "@angular/core";
import { SplashScreen } from "@ionic-native/splash-screen/ngx";
import { StatusBar } from "@ionic-native/status-bar/ngx";
import { Platform } from "@ionic/angular";
import { Router } from "@angular/router";

@Component({
  selector: "app-root",
  templateUrl: "app.component.html",
  styleUrls: ["app.component.scss"],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
  private TAB_ITEMS = [
    { url: "/tabs/1" },
    { url: "/tabs/2" },
    { url: "/tabs/3" },
  ];
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private router: Router
  ) {
    this.initializeApp();
  }

  initializeApp(): void {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

  get showMenu(): boolean {
    return !this.TAB_ITEMS.some((item) => this.router.url === item.url);
  }
}

On line 35 we have a showMenu getter and it has some router.url logic. We can use spies to test the showMenu, especially the spyOnProperty method of Jasmine framework.

Why we should you use the spyOnProperty instead of spyOn? Because url is property of router instance.

The full example of spec file for this component:


import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TestBed, waitForAsync } from '@angular/core/testing';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Platform } from '@ionic/angular';

import { AppComponent } from './app.component';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';

describe('AppComponent', () => {
  let statusBarSpy: jasmine.SpyObj<StatusBar>;
  let splashScreenSpy: jasmine.SpyObj<SplashScreen>;
  let platformReadySpy: Promise<void>;
  let platformSpy: jasmine.SpyObj<Platform>;
  let router: Router;

  beforeEach(waitForAsync(() => {
    statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
    splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
    platformReadySpy = Promise.resolve();
    platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy });

    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      providers: [
        { provide: StatusBar, useValue: statusBarSpy },
        { provide: SplashScreen, useValue: splashScreenSpy },
        { provide: Platform, useValue: platformSpy },
      ],
    }).compileComponents();
    router = TestBed.inject(Router);
  }));

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;

    expect(app).toBeTruthy();
  });

  it('should initialize the app', async () => {
    TestBed.createComponent(AppComponent);

    expect(platformSpy.ready).toHaveBeenCalledWith();
    await platformReadySpy;

    expect(statusBarSpy.styleDefault).toHaveBeenCalledWith();
    expect(splashScreenSpy.hide).toHaveBeenCalledWith();
  });

  it('should show menu be false', () => {
    const component = TestBed.createComponent(AppComponent);
    spyOnProperty(router, 'url', 'get').and.returnValue('/tabs/1');

    expect(component.componentInstance.showMenu).toBeFalse();
  });

  it('should show menu be true', () => {
    const component = TestBed.createComponent(AppComponent);
    spyOnProperty(router, 'url', 'get').and.returnValue('/some-page');

    expect(component.componentInstance.showMenu).toBeTruthy();
  });
});

Conclusion

In this post we have learned how to spy the url property of router instance in the Angular or Ionic application

comments powered by Disqus