Skip to content

Commit

Permalink
feat(routing): emit router events
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkluijk committed Sep 20, 2019
1 parent 7ad0d86 commit 19ede7e
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 18 deletions.
6 changes: 4 additions & 2 deletions projects/spectator/src/lib/mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/** Credit: Valentin Buryakov */
import { FactoryProvider, Type } from '@angular/core';

import { InjectableType } from './token';

type Writable<T> = { -readonly [P in keyof T]: T[P] };

/**
Expand Down Expand Up @@ -69,7 +71,7 @@ export function installProtoMethods<T>(mock: any, proto: any, createSpyFn: Funct
/**
* @publicApi
*/
export function createSpyObject<T>(type: Type<T>, template?: Partial<Record<keyof T, any>>): SpyObject<T> {
export function createSpyObject<T>(type: InjectableType<T>, template?: Partial<Record<keyof T, any>>): SpyObject<T> {
const mock: any = { ...template } || {};

installProtoMethods<T>(mock, type.prototype, name => {
Expand All @@ -89,7 +91,7 @@ export function createSpyObject<T>(type: Type<T>, template?: Partial<Record<keyo
/**
* @publicApi
*/
export function mockProvider<T>(type: Type<T>, properties?: Partial<Record<keyof T, any>>): FactoryProvider {
export function mockProvider<T>(type: InjectableType<T>, properties?: Partial<Record<keyof T, any>>): FactoryProvider {
return {
provide: type,
useFactory: () => createSpyObject(type, properties)
Expand Down
28 changes: 14 additions & 14 deletions projects/spectator/src/lib/spectator-routing/initial-module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRoute, Event, Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { EMPTY } from 'rxjs';
import { Subject } from 'rxjs';

import { ModuleMetadata } from '../base/initial-module';
import { initialSpectatorModule } from '../spectator/initial-module';
import { SpyObject } from '../mock';

import { ActivatedRouteStub } from './activated-route-stub';
import { SpectatorRoutingOptions } from './options';
import { RouterLinkDirectiveStub } from './router-link-stub';
import { RouterStub } from './router-stub';

/**
* @internal
Expand All @@ -21,18 +21,18 @@ export function initialRoutingModule<S>(options: Required<SpectatorRoutingOption
}

if (options.stubsEnabled) {
moduleMetadata.providers.push({
provide: Router,
useFactory: () => {
const provider = options.mockProvider(Router);
const router = provider.useFactory() as SpyObject<Router>;

// this prevents the events property to be undefined
router.castToWritable().events = EMPTY;

return router;
moduleMetadata.providers.push(
options.mockProvider(RouterStub, {
events: new Subject<Event>(),
emitRouterEvent(event: Event): void {
this.events.next(event);
}
}),
{
provide: Router,
useExisting: RouterStub
}
});
);

moduleMetadata.providers.push(
{
Expand Down
9 changes: 9 additions & 0 deletions projects/spectator/src/lib/spectator-routing/router-stub.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Router, Event } from '@angular/router';

export abstract class RouterStub extends Router {
public abstract emitRouterEvent(event: Event): void;
}

export function isRouterStub(router: Router): router is RouterStub {
return 'emitRouterEvent' in router;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { DebugElement } from '@angular/core';
import { ComponentFixture } from '@angular/core/testing';
import { Router } from '@angular/router';
import { Event, Router } from '@angular/router';

import { Spectator } from '../spectator/spectator';

import { ActivatedRouteStub } from './activated-route-stub';
import { RouteOptions } from './route-options';
import { isRouterStub } from './router-stub';

/**
* @publicApi
Expand Down Expand Up @@ -88,6 +89,23 @@ export class SpectatorRouting<C> extends Spectator<C> {
}
}

/**
* Emits a router event
*/
public emitRouterEvent(event: Event): void {
if (!isRouterStub(this.router)) {
// tslint:disable-next-line:no-console
console.warn(
'No stub for Router present. Set Spectator option "stubsEnabled" to true if you want to use this ' +
'helper, or use Router navigation to trigger events.'
);

return;
}

this.router.emitRouterEvent(event);
}

private triggerNavigationAndUpdate(): void {
this.activatedRouteStub!.triggerNavigation();
this.detectChanges();
Expand Down
30 changes: 29 additions & 1 deletion projects/spectator/test/with-routing/my-page.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Router, RouterLink } from '@angular/router';
import { NavigationStart, Router, RouterLink } from '@angular/router';
import { createRoutingFactory } from '@ngneat/spectator';
import { Component } from '@angular/core';
import { Location } from '@angular/common';
Expand Down Expand Up @@ -109,6 +109,22 @@ describe('MyPageComponent', () => {

expect(spectator.get(Router).navigate).toHaveBeenCalledWith(['bar']);
});

it('should trigger router events', async () => {
const spectator = createComponent();

const subscriberSpy = jasmine.createSpy('subscriber');
const subscription = spectator.router.events.subscribe(subscriberSpy);
spyOn(console, 'warn');

spectator.emitRouterEvent(new NavigationStart(1, 'some-url'));

// tslint:disable-next-line:no-console
expect(console.warn).not.toHaveBeenCalled();
expect(subscriberSpy).toHaveBeenCalled();

subscription.unsubscribe();
});
});

describe('without stubs', () => {
Expand Down Expand Up @@ -158,5 +174,17 @@ describe('MyPageComponent', () => {
await spectator.fixture.whenStable();
expect(spectator.get(Location).path()).toBe('/foo');
});

it('should not trigger router events', async () => {
const spectator = createComponent();
await spectator.fixture.whenStable();

spyOn(console, 'warn');

spectator.emitRouterEvent(new NavigationStart(1, 'some-url'));

// tslint:disable-next-line:no-console
expect(console.warn).toHaveBeenCalled();
});
});
});

0 comments on commit 19ede7e

Please sign in to comment.