0

I've recently upgrade to Angular 9.1.0-rc.2 and everything looks to be in a working order. I'm able to get the app served locally and on a server fine, however when running jasmine unit tests I'm getting the following error on random components every test:

    Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'not-found'
    Error: Cannot match any routes. URL Segment: 'not-found'
        at ApplyRedirects.noMatchError (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/@angular/router/fesm2015/router.js:4327:1)
        at CatchSubscriber.selector (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/@angular/router/fesm2015/router.js:4291:1)
        at CatchSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/operators/catchError.js:29:1)
        at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
        at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
        at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
        at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
        at MapSubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
        at MapSubscriber.error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:55:1)
        at ThrowIfEmptySubscriber._error (http://localhost:9876/Users/asithadesilva/Sites/my-project/node_modules/rxjs/_esm2015/internal/Subscriber.js:75:1)
    error properties: Object({ rejection: Error: Cannot match any routes. URL Segment: 'not-found', promise: [object Promise], zone: Zone({ _parent: Zone({ _parent: Zone({ _parent: Zone({ _parent: null, _name: '<root>', _properties: Object({  }), _zoneDelegate: ZoneDelegate({ _taskCounts: Object({ microTask: 0, macroTask: 0, eventTask: 0 }), zone: <circular reference: Object>, _parentDelegate: null, _forkZS: null, _forkDlgt: null, _forkCurrZone: null, _interceptZS: null, _interceptDlgt: null, _interceptCurrZone: null, _invokeZS: null, _invokeDlgt: null, _invokeCurrZone: null, _handleErrorZS: null, _handleErrorDlgt: null, _handleErrorCurrZone: null, _scheduleTaskZS: null, _scheduleTaskDlgt: null, _scheduleTaskCurrZone: null, _invokeTaskZS: null, _invokeTaskDlgt: null, _invokeTaskCurrZone: null, _cancelTaskZS: null, _cancelTaskDlgt: null, _cancelTaskCurrZone: null, _hasTaskZS: null, _hasTaskDlgt: null, _hasTaskDlgtOwner: null, _hasTaskCurrZone: null }) }), _name: 'ProxyZone', _properties: Object({ ProxyZo ...

Here is how I've setup my routes: app-routing.module.ts

import { MetaGuard } from '@ngx-meta/core';
import { UserModule } from './modules/user/user.module';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoggedInGuard } from 'ngx-auth-firebaseui';

import { AdminGuard } from '@shared/guards/admin.guard';
import { CourseModule } from './modules/course/course.module';
import { AdminModule } from './modules/admin/admin.module';
import { PagesModule } from './pages/pages.module';

const routes: Routes = [
  {
    path: '',
    loadChildren: async (): Promise<PagesModule> =>
      import('./pages/pages.module').then((m: { PagesModule: PagesModule }) => m.PagesModule)
  },
  {
    canActivateChild: [MetaGuard],
    path: 'admin',
    loadChildren: async (): Promise<AdminModule> =>
      import('./modules/admin/admin.module').then((m: { AdminModule: AdminModule }) => m.AdminModule),
    canActivate: [LoggedInGuard, AdminGuard]
  },
  {
    path: 'course',
    loadChildren: async (): Promise<CourseModule> =>
      import('./modules/course/course.module').then((m: { CourseModule: CourseModule }) => m.CourseModule),
    data: {
      title: 'Course'
    }
  },
  {
    path: '**',
    redirectTo: '/not-found',
    data: {
      title: 'Page Not Found'
    }
  }
];

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

pages-routing.module.ts

import { NotFoundComponent } from './not-found/not-found.component';
import { HomeComponent } from './home/home.component';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'not-found',
    component: NotFoundComponent
  }
];

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

app.module.ts

@NgModule({
  declarations: [AppComponent],
  imports: [
    CommonModule,
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MetaModule.forRoot({
      provide: MetaLoader,
      useFactory: metaFactory
    }),
    FirebaseModule,
    SharedModule,
    Angulartics2Module.forRoot({
      gst: {
        trackingIds: [environment.googleAnalytics]
      }
    })
  ],
  bootstrap: [AppComponent]
})

In the components that actually call this route: this.router.navigate(['not-found']);

Things I've tried:

  • Remove Async calls in Route
  • LazyLoad Children: loadChildren: './modules/course/course.module#CourseModule'
  • Set this.router.navigate(['/not-found'])
  • Loaded the NotFoundComponent directly in the main app-routing.module.ts
  • When I comment out any component that uses that route, the unit tests work fine.

Note that when I serve the app, I'm able to get to the not-found page. I'm kinda stuck on this, and would appreciate any hints on what could be causing this.

Asitha De Silva
  • 183
  • 1
  • 13
  • Why 2 route modules? – JWP Apr 01 '20 at 02:09
  • @JohnPeters because the other module is a child module with its own set of routes – Asitha De Silva Apr 01 '20 at 07:58
  • What happens when you combine both into one? – JWP Apr 01 '20 at 12:06
  • @JohnPeters the same thing. Initially I didn't have a PagesModule and directly called the NotFoundComponent within the AppRoutingModule but it did the same thing – Asitha De Silva Apr 01 '20 at 20:34
  • OK turn on route tracing. https://stackoverflow.com/questions/45669030/how-to-trace-routing-in-angular-2 or subscribe to all router.events so you can see what's happening within angular. Also, your app.module should be importing all components, and declaring them. They are not declaring any components. Which may mean that the loader cannot find them. So it may not be the inability to find the route, it could be the inability to load the component. – JWP Apr 01 '20 at 21:37
  • @JohnPeters https://gist.github.com/asithade/053b05cf8eac7fc04751930aa845c1fb - this is what happens when I try to navigate to a page that doesn't exist when serving the app. Unit tests don't return an error that's different to what I posted in the original post – Asitha De Silva Apr 01 '20 at 23:19
  • It looks like I was able to solve the issue with the answer provided here: https://stackoverflow.com/a/45315961/1432248 -- thanks for your help though @JohnPeters! – Asitha De Silva Apr 01 '20 at 23:30

1 Answers1

2

It looks like I was able to solve the issue thanks to the answer here: https://stackoverflow.com/a/45315961/1432248

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule.withRoutes([{ path: 'not-found', component: NotFoundComponent }]),
        ...,
      ],
      declarations: [..., NotFoundComponent],
    }).compileComponents();
  }));

Edit your RouterTestingModule and use withRoutes and add the path and component of the route that's missing. The original answer explains in detail on why this is happening.

Asitha De Silva
  • 183
  • 1
  • 13