firasKoubaa
firasKoubaa

Reputation: 6867

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 ??

Upvotes: 8

Views: 15966

Answers (1)

Supamiu
Supamiu

Reputation: 8731

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

Upvotes: 10

Related Questions