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();
});
});
In this post we have learned how to spy the url
property of router
instance in the Angular or Ionic application