Search code examples
angularjestjsangular-routerts-jest

Jest Angular test NavigationEnd


Here is my component code that i want to test:

allpages: Array<Page> = [
  { name: 'Home', url: '/home' },
];

constructor(private router: Router) {
    this.$routerEvent = this.router.events.subscribe((event: Event) => {
      if (event instanceof NavigationEnd) {
        let route = event.url !== '/' ? event.url : event.urlAfterRedirects;
        this.currentPage = this.allpages.find(
          (page) => page.url === route
        );
      }
    });
  }

Here is my test:

beforeEach(async () => {
  TestBed.configureTestingModule({
    declarations: [NavigationBarComponent],
    imports: [MatIconModule, RouterTestingModule],
  }).compileComponents();

  fixture = TestBed.createComponent(NavigationBarComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

it('should set home page as current page', inject([Router], (router: Router) => {
  router.initialNavigation();
  expect(component.currentPage).toEqual({ name: 'Home', url: '/home' });
}));

Test fails because component.currentPage = undefined.

I have read that navigation is an async operation, how do i properly should implement the test, or maybe i went absolutely incorrect way?


Solution

  • To test router events, we need to mock the router service object. In the test session configuration, we will replace events property of router as an Observable object. To have access to the events observable object, we create a separate variable of ReplaySubject<RouterEvent>.

     const eventSubject = new ReplaySubject<RouterEvent>(1);
    

    Crate a router mock

    const routerMock = {
         events: eventSubject.asObservable(),
     };
    

    While using mock object do not use RouterTestingModule
    Explanation:Angular 2 Final Release Router Unit Test

    beforeEach(async () => {
      TestBed.configureTestingModule({
        declarations: [NavigationBarComponent],
        imports: [MatIconModule],
        providers: [
            {provide: Router, useValue: routerMock} <-- Override with mock object
        ]
    
      }).compileComponents();
    
      fixture = TestBed.createComponent(NavigationBarComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    });
    
    it('should set home page as current page', () => {
       // simulate the navigation end events
        eventSubject.next(new NavigationEnd(1, '/home', '/urlAfterRedirect'));
        expect(app.currentPage).toEqual({ name: 'Home', url: '/home' });
    });
    

    Ref:Approach using Jasmine
    More