Angular routing unit testing: Breaking down routing testing into individual route testing sequences

Currently, I am in the process of testing the routing functionality of my Angular application:

Below is the file where I have declared the routes for my app:

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';

export 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 {}

Furthermore, here is the test file that I have created: app-routing.spec.ts :

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 {routes} from './app-routing.module';
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';
import {AppRoutingModule} from './app-routing.module';
import {CustomerDetailComponent} from './customer/customer-detail/customer-detail.component';
import {CustomersListComponent} from './customer/customers-list/customers-list.component';

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

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

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

    });
    router = TestBed.get(Router);
    location = TestBed.get(Location);
    fixture = TestBed.createComponent(AppComponent);
    router.initialNavigation();
  });

  it('When navigating to a route without specifying one, it should redirect to /login.', () => {
    router.navigate(['']).then(() => {
      expect(location.path()).toBe('/login');
    });
  });

The issue arises when trying to add another test case. For example, adding the following causes interference between routes:

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

An error occurs as shown below:

Expected '/inscription' to be '/login'.
    at webpack:///src/app/app-routing.spec.ts:65:30 <- src/test.ts:144329:37
    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:232587:39)
    at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:390:0 <- src/polyfills.ts:1545:32)

In order to resolve this issue, using the afterEach() loop might help, but the exact implementation is not clear to me.

Answer №1

To begin work, I simply include:

tick(50)

for each test case.

Below is the structure of the test case:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring diverse paging methods tailored to specific devices within Angular 12

Hey there! I'm looking to implement two different paginations for a single table with 20 rows. Here's what I need: For desktop, the first pagination should display 10 rows on the first page and the remaining 10 rows on the second page. As f ...

Utilizing Rxjs to transform an array of objects

My goal is to map an array of objects. Currently, I have the following code: return this.service.post(url, payload, this.httpOptions) .pipe( map((obj: any, index) => [({ ...obj, val1: obj[index].val1.id, v ...

The Angular ReactiveForm encounters issues with recognizing the parent formGroup directive when working with a recursive template

In my application, I generate formGroups dynamically based on a configuration object that follows this structure: const formElements: FormElementInterface[] = [ { type: 'formControl', defaultIsArray: false, defaultValue: 'Apple&ap ...

Struggling to locate the module 'firebase-admin/app' - Tips for resolving this issue?

While working with Typescript and firebase-admin for firebase cloud functions, I encountered the error message "Cannot find module 'firebase-admin/app'" when compiling the code with TS. Tried solutions: Reinstalling Dependency Deleting node_modu ...

Tips for troubleshooting the 404 error on nginx servers

I've got an angular 4 Single Page Application (SPA) and I'm using Docker for production. Everything seems to be going smoothly so far. When I navigate to the /dist folder in the terminal, I use the following command to point docker to the content ...

Using debounceTime and distinctUntilChanged in Angular 6 for efficient data handling

I recently came across a tutorial on RxJS that demonstrated the use of debounce and distinctUntilChanged. I'm trying to implement it in Angular 6, but I'm facing some challenges. Here is the code from the tutorial: var observable = Rx.Observabl ...

Changing the row property value of a textarea dynamically based on text input in ReactJS

Here is what I have tried: <textarea rows='2' onChange={e => setSomething(e.target.value)} className='form-control text-area ' value={something} placeholder='write something'> </textarea> output: Expected ...

Displaying a TypeScript-enabled antd tree component in a React application does not show any information

I attempted to convert the Tree example from antd to utilize TypeScript, however, the child-render function does not seem to return anything. The commented row renders when I remove the comment. The RenderTreeNodes function is executed for each element in ...

Invoke the subscribe function within the encompassing parent function

In crafting a versatile method, I have devised the following code snippet: fetchArticle(loading: Loading): void { this.articleService.getArticleById(this.data.definition.id) .map((response: any) => response.json()) .subscribe((response: ...

Automatically closing the AppDateTimePicker modal in Vuexy theme after selecting a date

I am currently developing a Vue.js application using the Vuexy theme. One issue I have encountered is with a datetimepicker within a modal. The problem arises when I try to select a date on the datetimepicker component - it closes the modal instead of stay ...

Following an update from typescript version 2.3.4 to 2.4.2, I encountered a compilation error stating, "The type definition file for 'reflect-metadata' cannot be found."

Recently, I encountered an issue with my React / Mobex application written in TypeScript and built by Webpack 1. Upon updating the TypeScript version from 2.3.4 to 2.4.2, an error started occurring. The error message reads: ERROR in C:\myproject&bsol ...

The functionality of the String prototype is operational in web browsers, but it encounters issues

Version: 8.1.0 The prototype I am working with is as follows: String.prototype.toSlug = function () { return (<string>this) .trim() .toLowerCase() .replace(/\s+/g, '-') .replace(/[^\w\-]+/g, '') ...

Change the variable value within the service simultaneously from various components

There is a service called DisplaysService that contains a variable called moneys. Whenever I make a purchase using the buy button on the buy component, I update the value of this variable in the service from the component. However, the updated value does n ...

Has anyone tried integrating Reveal JS with Angular 8?

Encountering a problem with the integration of Reveal JS in an Angular component. Despite being initialized after DOM processing, it is not displaying anything. What is the appropriate time to initialize the reveal library? Is there a way to incorporate ...

Angular - delay execution until the variable has a value

When the ngOnInit() function is called, the first line of code retrieves a value from local storage which is then used to filter data from the database. Both actions happen simultaneously, resulting in an issue where I don't receive the expected resu ...

What is the importance of a subclass providing services to a superclass in Angular?

While exploring some Angular code today, I stumbled upon this interesting snippet: export class ContentFormComponent extends FormBase { ... constructor( private authService: AuthService, private apiService: ApiService, private segmentService: Segme ...

The stack property of [object Object] cannot be updated, as it only has a getter method

I can't figure out why I'm receiving this specific error in the Plunker below. Cannot set property stack of [object Object] which has only a getter Access the Plunker here: https://plnkr.co/edit/IP1ssat2Gpu1Cra495u2?p=preview The code causi ...

Guide for transferring the body of a table to a different component without disrupting the design aesthetics

In an attempt to reorganize my large table component, I decided to separate its body section into a new component. However, every time I try to do this, the styling of the table breaks (likely due to the new HTML structure in the code). I'm currently ...

What is the safest method to convert a nested data structure into an immutable one while ensuring type safety when utilizing Immutable library?

When it comes to dealing with immutable data structures, Immutable provides the handy fromJs function. However, I've been facing issues trying to integrate it smoothly with Typescript. Here's what I've got: type SubData = { field1: strin ...

Angular fails to display newly created objects unless the page is manually refreshed

Hey there, I'm facing a problem with my message service on the user profile page. Even though messages are fetched from the database and displayed correctly, any changes (such as creating or deleting a message) are not reflected until I manually refre ...