Skip to content

Commit 868c694

Browse files
committed
perf: reduce strategy surface and make it a fn
1 parent a6d7cbe commit 868c694

7 files changed

+60
-79
lines changed
Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { MockProvider, MockService } from 'ng-mocks'
1+
import { MockService } from 'ng-mocks'
22
import { ActivatedRouteSnapshot } from '@angular/router'
3-
import { TestBed } from '@angular/core/testing'
43
import {
5-
CurrentRouteDataMetadataStrategy,
4+
CURRENT_ROUTE_DATA_METADATA_ROUTE_STRATEGY,
65
ROUTING_KEY,
76
} from './current-route-data-metadata-strategy'
8-
import { MetadataService } from '../../core'
97

108
describe('Current route data metadata strategy', () => {
9+
const sut = CURRENT_ROUTE_DATA_METADATA_ROUTE_STRATEGY
10+
1111
describe('resolve', () => {
1212
it('returns current route snapshot (last child)', () => {
1313
const dummyRouteMetadata = { title: 'dummy' }
@@ -20,19 +20,7 @@ describe('Current route data metadata strategy', () => {
2020
},
2121
},
2222
} as Partial<ActivatedRouteSnapshot>)
23-
const sut = makeSut()
24-
25-
expect(sut.resolve(rootSnapshot)).toEqual(dummyRouteMetadata)
23+
expect(sut(rootSnapshot)).toEqual(dummyRouteMetadata)
2624
})
2725
})
2826
})
29-
30-
function makeSut() {
31-
TestBed.configureTestingModule({
32-
providers: [
33-
CurrentRouteDataMetadataStrategy,
34-
MockProvider(MetadataService),
35-
],
36-
})
37-
return TestBed.inject(CurrentRouteDataMetadataStrategy)
38-
}
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
import { ActivatedRouteSnapshot } from '@angular/router'
2-
import { Injectable } from '@angular/core'
32
import { MetadataRouteStrategy } from './metadata-route-strategy'
4-
import { MetadataService, MetadataValues } from '@davidlj95/ngx-meta/core'
53
import { MetadataRouteData } from './metadata-route-data'
64

7-
@Injectable({ providedIn: 'root' })
8-
export class CurrentRouteDataMetadataStrategy implements MetadataRouteStrategy {
9-
constructor(private readonly metadataService: MetadataService) {}
10-
11-
resolve<T extends object>(
12-
routeSnapshot: ActivatedRouteSnapshot,
13-
): T | undefined {
14-
let currentRouteSnapshot: ActivatedRouteSnapshot = routeSnapshot
5+
export const CURRENT_ROUTE_DATA_METADATA_ROUTE_STRATEGY: MetadataRouteStrategy =
6+
(activatedRouteSnapshot) => {
7+
let currentRouteSnapshot: ActivatedRouteSnapshot = activatedRouteSnapshot
158
while (currentRouteSnapshot.firstChild != null) {
169
currentRouteSnapshot = currentRouteSnapshot.firstChild
1710
}
1811
return currentRouteSnapshot.data[ROUTING_KEY]
1912
}
2013

21-
set(metadata: MetadataValues | undefined): void {
22-
this.metadataService.set(metadata)
23-
}
24-
}
25-
2614
export const ROUTING_KEY: keyof MetadataRouteData = 'meta'
Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1+
import { InjectionToken } from '@angular/core'
12
import { ActivatedRouteSnapshot } from '@angular/router'
2-
import { MetadataValues } from '@davidlj95/ngx-meta/core'
33

4-
export abstract class MetadataRouteStrategy<
5-
Metadata extends MetadataValues = MetadataValues,
6-
> {
7-
public abstract resolve(
8-
routeSnapshot: ActivatedRouteSnapshot,
9-
): Metadata | undefined
4+
export type MetadataRouteStrategy = <T>(
5+
activatedRouteSnapshot: ActivatedRouteSnapshot,
6+
) => T | undefined
107

11-
public abstract set(metadata: Metadata | undefined): void
12-
}
8+
export const METADATA_ROUTE_STRATEGY = new InjectionToken(
9+
ngDevMode ? 'NgxMeta Metadata Route Strategy' : 'NgxMetaMRS',
10+
)

projects/ngx-meta/src/routing/src/provide-routing.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@ import {
22
ENVIRONMENT_INITIALIZER,
33
EnvironmentProviders,
44
Provider,
5+
ValueProvider,
56
} from '@angular/core'
6-
import { CurrentRouteDataMetadataStrategy } from './current-route-data-metadata-strategy'
7-
import { MetadataRouteStrategy } from './metadata-route-strategy'
87
import { RouterListenerService } from './router-listener.service'
9-
10-
export const DEFAULT_METADATA_STRATEGY_PROVIDER: Provider = {
11-
provide: MetadataRouteStrategy,
12-
useExisting: CurrentRouteDataMetadataStrategy,
13-
}
8+
import { CURRENT_ROUTE_DATA_METADATA_ROUTE_STRATEGY } from './current-route-data-metadata-strategy'
9+
import { METADATA_ROUTE_STRATEGY } from './metadata-route-strategy'
1410

1511
export const ROUTING_INITIALIZER: Provider = {
1612
provide: ENVIRONMENT_INITIALIZER,
@@ -23,6 +19,15 @@ export const ROUTING_INITIALIZER: Provider = {
2319
deps: [RouterListenerService],
2420
}
2521

26-
export function provideRouting(): EnvironmentProviders | Provider[] {
27-
return [DEFAULT_METADATA_STRATEGY_PROVIDER, ROUTING_INITIALIZER]
22+
export const DEFAULT_METADATA_ROUTE_STRATEGY: ValueProvider = {
23+
provide: METADATA_ROUTE_STRATEGY,
24+
useValue: CURRENT_ROUTE_DATA_METADATA_ROUTE_STRATEGY,
2825
}
26+
27+
export const ROUTING_PROVIDERS = [
28+
DEFAULT_METADATA_ROUTE_STRATEGY,
29+
ROUTING_INITIALIZER,
30+
]
31+
32+
export const provideRouting = (): EnvironmentProviders | Provider[] =>
33+
ROUTING_PROVIDERS

projects/ngx-meta/src/routing/src/router-listener.service.spec.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ import {
1010
RouterEvent,
1111
} from '@angular/router'
1212
import { EventEmitter, Provider } from '@angular/core'
13-
import { MetadataRouteStrategy } from './metadata-route-strategy'
13+
import {
14+
METADATA_ROUTE_STRATEGY,
15+
MetadataRouteStrategy,
16+
} from './metadata-route-strategy'
1417
import { enableAutoSpy } from '@davidlj95/ngx-meta/__tests__/enable-auto-spy'
1518
import { Subscription } from 'rxjs'
19+
import { MetadataService } from '../../core'
1620

1721
describe('RouterListenerService', () => {
1822
enableAutoSpy()
@@ -66,14 +70,17 @@ describe('RouterListenerService', () => {
6670
describe('when a non-end navigation event is triggered', () => {
6771
it('should not call any metadata strategy method', () => {
6872
const events$ = new EventEmitter()
69-
const strategy = makeStrategy()
73+
const strategy = jasmine.createSpy()
7074
const sut = makeSut({ events$, strategy })
75+
const metadataService = TestBed.inject(
76+
MetadataService,
77+
) as unknown as jasmine.SpyObj<MetadataService>
7178
sut.listen()
7279

7380
events$.emit(makeNavigationEvent(EventType.ActivationEnd))
7481

75-
expect(strategy.resolve).not.toHaveBeenCalled()
76-
expect(strategy.set).not.toHaveBeenCalled()
82+
expect(strategy).not.toHaveBeenCalled()
83+
expect(metadataService.set).not.toHaveBeenCalled()
7784
})
7885
})
7986

@@ -95,25 +102,27 @@ describe('RouterListenerService', () => {
95102
})
96103

97104
describe('when a strategy is provided', () => {
98-
it('should call strategy resolve and set', () => {
105+
it('should call strategy resolve and set that metadata', () => {
99106
const metadata = { key: 'value' }
100-
const strategy = makeStrategy('single', metadata)
107+
const strategy = jasmine.createSpy().and.returnValue(metadata)
101108
const events$ = new EventEmitter()
102109
const activatedRoute = MockService(ActivatedRoute)
103110
const sut = makeSut({
104111
events$,
105112
strategy,
106113
activatedRoute,
107114
})
115+
const metadataService = TestBed.inject(
116+
MetadataService,
117+
) as unknown as jasmine.SpyObj<MetadataService>
108118

109119
sut.listen()
110120

111121
events$.emit(makeNavigationEvent(EventType.NavigationEnd))
112122

113-
expect(strategy.resolve).toHaveBeenCalledOnceWith(
114-
activatedRoute.snapshot,
115-
)
116-
expect(strategy.set).toHaveBeenCalledOnceWith(metadata)
123+
expect(strategy).toHaveBeenCalledOnceWith(activatedRoute.snapshot)
124+
expect()
125+
expect(metadataService.set).toHaveBeenCalledOnceWith(metadata)
117126
})
118127
})
119128
})
@@ -137,11 +146,12 @@ function makeSut(
137146
RouterListenerService,
138147
MockProvider(Router, { events: events$ } as Partial<Router>, 'useValue'),
139148
MockProvider(ActivatedRoute, activatedRoute, 'useValue'),
149+
MockProvider(MetadataService),
140150
]
141151

142152
if (opts.strategy) {
143153
providers.push(
144-
MockProvider(MetadataRouteStrategy, opts.strategy, 'useValue'),
154+
MockProvider(METADATA_ROUTE_STRATEGY, opts.strategy, 'useValue'),
145155
)
146156
}
147157

@@ -152,16 +162,6 @@ function makeSut(
152162
return TestBed.inject(RouterListenerService)
153163
}
154164

155-
function makeStrategy(
156-
name: string = 'default',
157-
resolvedData: unknown = { dummy: 'metadata' },
158-
): jasmine.SpyObj<MetadataRouteStrategy> {
159-
return MockService(MetadataRouteStrategy, {
160-
resolve: jasmine.createSpy(`${name} resolve`).and.returnValue(resolvedData),
161-
set: jasmine.createSpy(`${name} set`),
162-
}) as jasmine.SpyObj<MetadataRouteStrategy>
163-
}
164-
165165
function makeNavigationEvent(type: EventType): NavigationEvent {
166166
return { type } as NavigationEvent
167167
}

projects/ngx-meta/src/routing/src/router-listener.service.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { Inject, Injectable, OnDestroy, Optional } from '@angular/core'
22
import { ActivatedRoute, EventType, Router } from '@angular/router'
33
import { filter, Subscription } from 'rxjs'
4-
import { MetadataRouteStrategy } from './metadata-route-strategy'
4+
import {
5+
METADATA_ROUTE_STRATEGY,
6+
MetadataRouteStrategy,
7+
} from './metadata-route-strategy'
8+
import { MetadataService } from '@davidlj95/ngx-meta/core'
59

610
@Injectable({ providedIn: 'root' })
711
export class RouterListenerService implements OnDestroy {
@@ -13,8 +17,9 @@ export class RouterListenerService implements OnDestroy {
1317
private readonly router: Router,
1418
private readonly activatedRoute: ActivatedRoute,
1519
@Optional()
16-
@Inject(MetadataRouteStrategy)
20+
@Inject(METADATA_ROUTE_STRATEGY)
1721
private readonly strategy: MetadataRouteStrategy | null,
22+
private readonly metadataService: MetadataService,
1823
) {}
1924

2025
public listen() {
@@ -44,7 +49,7 @@ export class RouterListenerService implements OnDestroy {
4449
}
4550
return
4651
}
47-
this.strategy.set(this.strategy.resolve(this.activatedRoute.snapshot))
52+
this.metadataService.set(this.strategy(this.activatedRoute.snapshot))
4853
},
4954
})
5055
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { ModuleWithProviders, NgModule } from '@angular/core'
2-
import {
3-
DEFAULT_METADATA_STRATEGY_PROVIDER,
4-
ROUTING_INITIALIZER,
5-
} from './provide-routing'
2+
import { ROUTING_PROVIDERS } from './provide-routing'
63

74
@NgModule()
85
export class RoutingModule {
96
static forRoot(): ModuleWithProviders<RoutingModule> {
107
return {
118
ngModule: RoutingModule,
12-
providers: [DEFAULT_METADATA_STRATEGY_PROVIDER, ROUTING_INITIALIZER],
9+
providers: ROUTING_PROVIDERS,
1310
}
1411
}
1512
}

0 commit comments

Comments
 (0)