W3cubDocs

/Angular

RouterTestingHarness

class final

A testing harness for the Router to reduce the boilerplate needed to test routes and routed components.

class RouterTestingHarness {
  static create(initialUrl?: string): Promise<RouterTestingHarness>
  routeDebugElement: DebugElement | null
  routeNativeElement: HTMLElement | null
  detectChanges(): void
  navigateByUrl<T>(url: string, requiredRoutedComponentType?: Type<T>): Promise<T | null>
}

Static methods

Creates a RouterTestingHarness instance.

static create(initialUrl?: string): Promise<RouterTestingHarness>

Parameters
initialUrl string

The target of navigation to trigger before returning the harness.

Optional. Default is undefined.

Returns

Promise<RouterTestingHarness>

The RouterTestingHarness also creates its own root component with a RouterOutlet for the purposes of rendering route components.

Throws an error if an instance has already been created. Use of this harness also requires destroyAfterEach: true in the ModuleTeardownOptions

Properties

Property Description
routeDebugElement: DebugElement | null Read-Only

The DebugElement of the RouterOutlet component. null if the outlet is not activated.

routeNativeElement: HTMLElement | null Read-Only

The native element of the RouterOutlet component. null if the outlet is not activated.

Methods

Instructs the root fixture to run change detection.

detectChanges(): void

Parameters

There are no parameters.

Returns

void

Triggers a Router navigation and waits for it to complete.

navigateByUrl(url: string): Promise<null | {}>

Parameters
url string

The target of the navigation. Passed to Router.navigateByUrl.

Returns

Promise<null | {}>: The activated component instance of the RouterOutlet after navigation completes (null if the outlet does not get activated).

Triggers a router navigation and waits for it to complete.

navigateByUrl<T>(url: string, requiredRoutedComponentType: Type<T>): Promise<T>

Parameters
url string

The target of the navigation. Passed to Router.navigateByUrl.

requiredRoutedComponentType Type<T>

After navigation completes, the required type for the activated component of the RouterOutlet. If the outlet is not activated or a different component is activated, this function will throw an error.

Returns

Promise<T>: The activated component instance of the RouterOutlet after navigation completes.

The root component with a RouterOutlet created for the harness is used to render Route components.

it('navigates to routed component', async () => {
  @Component({standalone: true, template: 'hello {{name}}'})
  class TestCmp {
    name = 'world';
  }

  TestBed.configureTestingModule({
    providers: [provideRouter([{path: '', component: TestCmp}])],
  });

  const harness = await RouterTestingHarness.create();
  const activatedComponent = await harness.navigateByUrl('/', TestCmp);
  expect(activatedComponent).toBeInstanceOf(TestCmp);
  expect(harness.routeNativeElement?.innerHTML).toContain('hello world');
});

The root component is reused within the same test in subsequent calls to navigateByUrl.

This function also makes it easier to test components that depend on ActivatedRoute data.

@Component({
  standalone: true,
  imports: [AsyncPipe],
  template: `search: {{(route.queryParams | async)?.query}}`
})
class SearchCmp {
  constructor(readonly route: ActivatedRoute, readonly router: Router) {}

  async searchFor(thing: string) {
    await this.router.navigate([], {queryParams: {query: thing}});
  }
}

TestBed.configureTestingModule({
  providers: [provideRouter([{path: 'search', component: SearchCmp}])],
});

const harness = await RouterTestingHarness.create();
const activatedComponent = await harness.navigateByUrl('/search', SearchCmp);
await activatedComponent.searchFor('books');
harness.detectChanges();
expect(TestBed.inject(Router).url).toEqual('/search?query=books');
expect(harness.routeNativeElement?.innerHTML).toContain('books');

The root component with a RouterOutlet created for the harness is used to render Route components. The root component is reused within the same test in subsequent calls to navigateForTest.

When testing Routes with a guards that reject the navigation, the RouterOutlet might not be activated and the activatedComponent may be null.

let isLoggedIn = false;
const isLoggedInGuard: CanActivateFn = () => {
  return isLoggedIn ? true : inject(Router).parseUrl('/login');
};

TestBed.configureTestingModule({
  providers: [
    provideRouter([
      {path: 'admin', canActivate: [isLoggedInGuard], component: AdminComponent},
      {path: 'login', component: LoginComponent},
    ]),
  ],
});

const harness = await RouterTestingHarness.create('/admin');
expect(TestBed.inject(Router).url).toEqual('/login');
isLoggedIn = true;
await harness.navigateByUrl('/admin');
expect(TestBed.inject(Router).url).toEqual('/admin');

© 2010–2023 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://angular.io/api/router/testing/RouterTestingHarness