Exploring Angular 8 Routing Testing within a Service

I am currently in the process of testing an Http Interception service that utilizes routing to redirect to another URL upon encountering an error response. All of my tests are passing smoothly since I am not specifically testing the routing functionality itself, however, an exception keeps popping up on my console.

Unhandled Promise rejection: Cannot match any routes. URL Segment: 'login' ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Cannot match any routes. URL Segment: 'login'

Despite attempting to put a spy on my router service for the navigateByUrl function, it seems like the spy is not being invoked as expected, resulting in the persistent occurrence of the same error. I have experimented with RouterTestingModule and Router Stubbing, but it appears that my service is utilizing a different Router Service rather than the one provided in my .spec file.

Below is a snippet of my .spec code (I have withheld the URL for confidentiality reasons):

import { TestBed } from '@angular/core/testing';
import { AuthInterceptorService } from './auth-interceptor.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpService } from '../http/http.service';
import { InternalDataService } from '../internal-data/internal-data.service';
import { Router } from '@angular/router';

describe('Service: AuthInterceptor', () => {
  let service: HttpService;
  let httpMock: HttpTestingController;
  let data: InternalDataService;
  let router = {
    navigate: jasmine.createSpy('navigateByUrl')
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule, 
      ],
      providers: [  
        HttpService, 
        InternalDataService, 
        { 
          provide: HTTP_INTERCEPTORS, 
          useClass: AuthInterceptorService, 
          multi: true 
        }, 
        {
          provide: Router, 
          useValue: router,
        }
      ],
    });

    service = TestBed.get(HttpService);
    httpMock = TestBed.get(HttpTestingController);
    router.navigate.and.callFake(() => {});
  });

  it('should add authentication header', () => {
    data = TestBed.get(InternalDataService);
    data.setAuthToken('Test');

    service.getProducts().subscribe(res => {
      expect(res).toBeTruthy();
    })

    const httpRequest = httpMock.expectOne('<doesnt matter>');
    expect(httpRequest.request.headers.has('Authorization')).toEqual(true);
    expect(httpRequest.request.headers.get('Authorization')).toEqual('Token Test');
  });

Below is the code snippet for my Service:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { InternalDataService } from '../internal-data/internal-data.service';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthInterceptorService implements HttpInterceptor {
  private token: string;

  constructor(private internal: InternalDataService, private router: Router) {
    this.internal.getAuthToken.subscribe( msg => this.token = msg );
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if(request.url.match('.*\/auth$') == null) { // ignore if it's an authentication url
      request = request.clone({
        setHeaders: {
          Authorization: `Token ${this.token}`
        }
      });
    }

    return next.handle(request).pipe(
      catchError((error: HttpErrorResponse) => {
        if(error.status == 401 || error.status == 403){
          this.internal.setIsAuth(false);
          this.router.navigateByUrl('/login');
        }
        return throwError(error);
      })
    );
  }
}

If anyone can pinpoint what might be going wrong here, your insight would be greatly appreciated.

Answer №1

After some investigation, I determined the root cause of the problem. It turns out that another test was also triggering the same issue. Fortunately, the problem lies within that specific test and not in our code. The current implementation is now functioning correctly.

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

Expanding Generic Interfaces in Typescript

I am working on a project where I need to enhance a typescript type by adding a new property in order to extend a generic type. To achieve this, I plan to define a Confidence<any> type that has the following structure: export interface Confidence< ...

The 'fullDocument' property is not present in the 'ChangeStreamDropDocument' type

Upon cloning an express TypeScript project, I encountered a Typescript error within a Mongo related function as mentioned in the title. Property 'fullDocument' does not exist on type 'ChangeStreamDocument<IUser>'. Property &apos ...

What is the best way to target changing elements displayed by *ngIf?

Trying to access a dynamic element generated by ngIf in the code below has proven to be challenging. I attempted two different methods: Using ElementRef and querySelector Component template: `<div class="test" *ngIf="expr"> <a id="b ...

Adding rows dynamically to a table in Angular can be achieved with ease

Looking to dynamically add a row to a table in my code snippet below! <tr *ngIf="customer"> <td>4</td> <td> <input type="text" name="firstName" required minlength="2"> </td> <td> <input type="te ...

Angular: Implementing ngIf within ngFor for Dynamic Content Display

I'm working on dynamically populating a list with conditional rendering for each list item, where the condition can be changed by user input. For instance: app.component.ts private check = true; private some = [ {name: 'ABC', cond ...

Trouble retrieving query parameters from a URL while trying to access URL parameters from a module

I am currently learning angular and facing a small problem that I'm unsure how to solve. My module looks like this: const hostHandler = setContext((operation: any, context: any) => ({ headers: { ...context?.headers, 'X-Location-Hostn ...

Issue with displaying data using a custom pure pipe and boolean in ngIf condition

For my current web project, I require a friendship/follow feature. There are two roles involved: admins and regular users. Regular users have the ability to follow other users, while admins do not possess this capability. When a user wishes to follow anot ...

Koffi organized a collection of structured arrays

I am currently using koffi 2.4.2 in a node.js application from koffi.dev and up until now, everything has been running smoothly. However, I have encountered an issue with integrating a native C++ library method that requires a parameter struct defined as f ...

Typescript error in Express: The property 'body' is not found on the type 'Request'

I found this code snippet: import bodyParser from 'body-parser'; import express, { Router } from 'express'; const router: Router = express.Router(); router.use(bodyParser.json()); router.post('/api/users/signup', (req: expr ...

Converting javascript html object lowercase

Is there a way to dynamically adjust the height of specific letters in my label? Right now, I am overriding the text for the elements: let element = document.getElementById('xxx') element.textContent = 'Label' I attempted using <sup ...

Modify a property within an object and then emit the entire object as an Observable

I currently have an object structured in the following way: const obj: SomeType = { images: {imageOrder1: imageLink, imageOrder2: imageLink}, imageOrder: [imageOrder1, imageOrder2] } The task at hand is to update each image within the obj.images array ...

"Customizing API requests based on specific conditions with n

For a specific scenario, I need to login as an admin in one case and as a regular user in another. signIn$ = createEffect(() => this.actions$.pipe( ofType(AuthActions.signInRequest), exhaustMap(({ variables, redirectTo, hasAdmin }) =&g ...

Empowering your Angular2 application with data binding

I am currently working with the following template: <table width="700"> <caption>All Users</caption> <thead> <tr> <th>name</th> <th>surname</th> < ...

Obtaining Prisma arguments by providing the table name as a string

Is there a way to retrieve the query arguments for a Prisma function by only passing the table name? Currently, I know I can obtain the table by providing the table name as a string in the following manner: function (tablename: string) { await prisma.[tab ...

What is the best way to display the loan detail and credit detail tables beneath the application detail section that is currently blank?

I have a total of four tables on my page. The size of one table is almost identical to the other three smaller tables. I am looking to place the loan details and credit details table below the application detail, in a way that utilizes the empty space avai ...

TypeError: Unable to find TextEncoder in mongoose and jest when using TypeScript

Currently, I am working on a project using Node 14 along with Express v4.16.3 and Typescript (v4.7.4). Recently, I added Mongoose (v6.5.2) to the project, and while the logic code seems fine, most of the tests executed by Jest (v26.4.2) are failing with th ...

Troubleshooting the ngx-image-zoom dependency error: How to resolve the unresolved dependency issue

When working on an angular project in version 10, I encountered challenges while installing the ngx-image-zoom component due to dependencies with angular 10. Despite this, I managed to resolve the issues. However, in my current project using angular 11, I ...

Experience the latest happenings in SAP Spartacus 4.0 by signing up for updates directly from

I am facing an issue while trying to register an event in Spartacus import { Injectable } from '@angular/core'; import { CartDetailsComponent, PromotionService} from '@spartacus/storefront'; import { ActiveCartService, SelectiveCartServ ...

Tips for activating AG Grid Column Auto Sizing on your website

The Issue I am experiencing difficulty in getting columns to expand to the size of their content upon grid rendering. Despite following the guidance provided in the official documentation example, and consulting sources such as Stack Overflow, I have att ...

Unloading a dynamically-loaded child component in Vue.js from the keep-alive cache

I have a question that is similar to the one mentioned here: Vue.js - Destroy a cached component from keep alive I am working on creating a Tab System using Vue router, and my code looks something like this: //My Tab component <template> <tab& ...