From 5866a59ed920fdbdba04550e74ae67b4f4f0f2fb Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Fri, 29 Jan 2021 14:18:57 +0300 Subject: [PATCH] add a service for getting navigation events stream --- .../packages/core/src/lib/services/index.ts | 1 + .../lib/services/navigation-events.service.ts | 36 +++++++++ .../tests/navigation-events.service.spec.ts | 75 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/services/navigation-events.service.ts create mode 100644 npm/ng-packs/packages/core/src/lib/tests/navigation-events.service.spec.ts diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index 37bc78d606..7044831681 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -9,6 +9,7 @@ export * from './lazy-load.service'; export * from './list.service'; export * from './localization.service'; export * from './multi-tenancy.service'; +export * from './navigation-events.service'; export * from './permission.service'; export * from './profile-state.service'; export * from './profile.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/navigation-events.service.ts b/npm/ng-packs/packages/core/src/lib/services/navigation-events.service.ts new file mode 100644 index 0000000000..ff18b65ed3 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/navigation-events.service.ts @@ -0,0 +1,36 @@ +import { Injectable, Type } from '@angular/core'; +import { + NavigationCancel, + NavigationEnd, + NavigationError, + NavigationStart, + Router, + RouterEvent, +} from '@angular/router'; +import { filter } from 'rxjs/operators'; + +export type NavigationEventType = 'Cancel' | 'End' | 'Error' | 'Start'; + +@Injectable({ providedIn: 'root' }) +export class NavigationEvents { + private eventTypes = new Map>([ + ['Cancel', NavigationCancel], + ['End', NavigationEnd], + ['Error', NavigationError], + ['Start', NavigationStart], + ]); + + constructor(private router: Router) {} + + getOneOf(...eventTypes: NavigationEventType[]) { + return this.router.events.pipe( + filter((event: RouterEvent) => + eventTypes.some(type => event instanceof this.eventTypes.get(type)), + ), + ); + } + + getAny() { + return this.getOneOf(...this.eventTypes.keys()); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/tests/navigation-events.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/navigation-events.service.spec.ts new file mode 100644 index 0000000000..cf6d2992d0 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/navigation-events.service.spec.ts @@ -0,0 +1,75 @@ +import { + NavigationCancel, + NavigationEnd, + NavigationError, + NavigationStart, + Router, + RouterEvent, +} from '@angular/router'; +import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest'; +import { Subject } from 'rxjs'; +import { take } from 'rxjs/operators'; +import { NavigationEvents } from '../services/navigation-events.service'; + +describe('NavigationEvents', () => { + let spectator: SpectatorService; + let service: NavigationEvents; + const events = new Subject(); + + const createService = createServiceFactory({ + service: NavigationEvents, + providers: [ + { + provide: Router, + useValue: { events }, + }, + ], + }); + + beforeEach(() => { + spectator = createService(); + service = spectator.service; + }); + + describe('getOneOf', () => { + test.each` + filtered | expected + ${['Start', 'Cancel']} | ${[0, 3]} + ${['Error', 'Cancel']} | ${[0, 1]} + ${['Start', 'End']} | ${[2, 3]} + ${['Error', 'End']} | ${[1, 2]} + `('should return a stream of given navigation events', ({ filtered, expected }) => { + const stream = service.getOneOf(...filtered); + const collected: number[] = []; + + stream.pipe(take(2)).subscribe(event => collected.push(event.id)); + + events.next(new NavigationCancel(0, null, null)); + events.next(new NavigationError(1, null, null)); + events.next(new NavigationEnd(2, null, null)); + events.next(new NavigationStart(3, null, null)); + + expect(collected).toEqual(expected); + }); + }); + + describe('getAny', () => { + it('should return a stream of any navigation event', () => { + const stream = service.getAny(); + const collected: number[] = []; + + stream.pipe(take(4)).subscribe(event => collected.push(event.id)); + + events.next(new RouterEvent(0, null)); + events.next(new NavigationStart(1, null, null)); + events.next(new RouterEvent(2, null)); + events.next(new RouterEvent(3, null)); + events.next(new NavigationError(4, null, null)); + events.next(new NavigationEnd(5, null, null)); + events.next(new RouterEvent(6, null)); + events.next(new NavigationCancel(7, null, null)); + + expect(collected).toEqual([1, 4, 5, 7]); + }); + }); +});