Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: Unit Testing Routing : Expected '' to be '/route'

Am working on unit testing for my routing under my Angular app ,

My routes are delacred in a specific module which is imported under the app.module.ts ,

here is my routing module:

app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { LoginComponent } from './login/login.component';
import { WelcomeComponent } from './welcome/welcome.component';
import { CustomersListComponent } from './customer/customers-list/customers-list.component';
import { CustomerDetailComponent } from './customer/customer-detail/customer-detail.component';
import { ApplicationParametersComponent } from './superAdministrator/application-parameters/application-parameters.component';
import { InscriptionComponent } from './inscription/inscription.component';

const routes: Routes = [
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: 'login',  component: LoginComponent },
  { path: 'login/:keyWording',  component: LoginComponent },
  { path: 'welcome', component: WelcomeComponent },
  { path: 'customers-list', component: CustomersListComponent },
  { path: 'customer-create', component: CustomerDetailComponent },
  { path: 'customer-detail/:idCustomer', component: CustomerDetailComponent },
  { path: 'application-parameters', component: ApplicationParametersComponent },
  { path: 'inscription', component: InscriptionComponent }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes) ],
  exports: [ RouterModule ]
})
export class AppRoutingModule {}

Here is my app.module.ts (where am used to import the routing module :

import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { SharedModule } from './../shared/shared.module';
import { LoginComponent } from './login/login.component';
import { WelcomeComponent } from './welcome/welcome.component';
import { AppComponent } from './app.component';
import { CustomerModule } from './customer/customer.module';
import { ApplicationParametersComponent } from './superAdministrator/application-parameters/application-parameters.component';
import { InscriptionComponent } from './inscription/inscription.component';

import { DxProgressBarModule } from 'devextreme-angular';

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    WelcomeComponent,
    ApplicationParametersComponent,
    InscriptionComponent
  ],
  imports: [
    AppRoutingModule, /* HERE IS THE ROUTING FILE */

    SharedModule,
    CustomerModule,
    DxProgressBarModule/*,
    BrowserAnimationsModule,
    BrowserModule*/
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Under my test file , i followed the tuto from this blog : https://codecraft.tv/courses/angular/unit-testing/routing/

My test file for the routing testing is the following :

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
// DevExtreme Module
import {DxProgressBarModule, DxTemplateModule} from 'devextreme-angular';
// Router Modules
import {RouterTestingModule} from '@angular/router/testing';
// Services and HTTP Module
import { SessionService } from './../shared/service';
import { HttpService } from './../shared/service';
import {HttpModule} from '@angular/http';
// Routs testing
import {Router, RouterModule} from '@angular/router';
import {fakeAsync, tick} from '@angular/core/testing';
import {Location} from '@angular/common';
import {LoginComponent} from './login/login.component';
import {WelcomeComponent} from './welcome/welcome.component';
import {ApplicationParametersComponent} from './superAdministrator/application-parameters/application-parameters.component';
import {InscriptionComponent} from './inscription/inscription.component';
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {FormsModule} from '@angular/forms';


describe('Testing the application routes', () => {

  let location: Location;
  let router: Router;
  let fixture;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule, FormsModule , DxTemplateModule , HttpModule ],
      providers:    [SessionService , HttpService ],
      declarations: [
        AppComponent,
        LoginComponent,
        WelcomeComponent,
        ApplicationParametersComponent,
        InscriptionComponent
      ],
      schemas: [ CUSTOM_ELEMENTS_SCHEMA ]

    });

    router = TestBed.get(Router);
    location = TestBed.get(Location);

    fixture = TestBed.createComponent(AppComponent);
    router.initialNavigation();
  });

  it('navigate to "inscription" takes you to /inscription', fakeAsync(() => {
    router.navigate(['inscription']);
    tick();
    expect(location.path()).toBe('/inscription');
  }));
});

My test fails , indicating this :

Expected '' to be '/inscription'.
    at Object.<anonymous> (webpack:///src/app/app-routing.spec.ts:52:28 <- src/test.ts:143891:33)
    at Object.<anonymous> (webpack:///~/@angular/core/@angular/core/testing.es5.js:348:0 <- src/test.ts:34691:26)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:391:0 <- src/polyfills.ts:1546:26)
    at ProxyZoneSpec.Array.concat.ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- src/test.ts:232357:39)

Ideas ??

like image 820
firasKoubaa Avatar asked Aug 08 '17 09:08

firasKoubaa


People also ask

What is the default route in Angular?

Default is "/" (the root path). The path-matching strategy, one of 'prefix' or 'full'. Default is 'prefix'. By default, the router checks URL elements from the left to see if the URL matches a given path and stops when there is a config match.

How do I test my router navigate in Angular jest?

router = TestBed. get(Router); Then, in the testcase, it('should show news intially ', () => { const navigateSpy = spyOn(router,'navigate'); component.

How do I test a router navigate in Angular 12?

We can test routing in Angular by using RouterTestingModule instead of RouterModule to provide our routes. This uses a spy implementation of Location which doesn't trigger a request for a new URL but does let us know the target URL which we can use in our test specs.

What is RouterTestingModule?

RouterTestingModulelinkSets up the router to be used for testing. class RouterTestingModule { static withRoutes(routes: Routes, config?: ExtraOptions): ModuleWithProviders<RouterTestingModule> }


1 Answers

You forgot to import routes to the RouterTestingModule, in your test file.

You have to add export keyword to your const routes in your AppRoutingModule file, then you can import the routes in your test file ( and add them in your test configuration).

import {routes} from '...'; // I don't have the app-routing.module file path.
...
...
...
 beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes(routes), <-- I added the routes here.
                FormsModule , DxTemplateModule , HttpModule 
  ],
      providers:    [SessionService , HttpService ],
      declarations: [
        AppComponent,
        LoginComponent,
        WelcomeComponent,
        ApplicationParametersComponent,
        InscriptionComponent
      ],
      schemas: [ CUSTOM_ELEMENTS_SCHEMA ]

    });

    router = TestBed.get(Router);
    location = TestBed.get(Location);

    fixture = TestBed.createComponent(AppComponent);
    router.initialNavigation();
  });

If you don't load routes in the router testing modules, it won't be able to know where to go when you navigate, so it will get back to original page with an error in console.

The tutorial you followed has a very strange way to handle routing because tick() is used for fakeAsync tests and this is a real async one. So you have to use the Promise<boolean> returned by router.navigate:

it('navigate to "inscription" takes you to /inscription', () => {
    router.navigate(['inscription']).then(() => {
        expect(location.path()).toBe('/inscription');
    });
});

As you see you can also remove fakeAsync because this is not fake, it's an async call.

See it on plunkr

like image 78
Supamiu Avatar answered Oct 15 '22 07:10

Supamiu