Skip to content

Commit d874cfc

Browse files
timdeschryverbrandonroberts
authored andcommitted
feat(router-store): add routerState config option (#1847)
Closes #1834
1 parent 29c426b commit d874cfc

File tree

13 files changed

+423
-126
lines changed

13 files changed

+423
-126
lines changed

modules/router-store/spec/router_store_module.spec.ts

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { TestBed } from '@angular/core/testing';
2-
import { Router } from '@angular/router';
2+
import { Router, RouterEvent } from '@angular/router';
33
import {
44
routerReducer,
55
RouterReducerState,
66
StoreRouterConnectingModule,
7+
RouterAction,
8+
RouterState,
9+
RouterStateSerializer,
10+
MinimalRouterStateSerializer,
11+
DefaultRouterStateSerializer,
712
} from '@ngrx/router-store';
8-
import { select, Store } from '@ngrx/store';
9-
import { withLatestFrom } from 'rxjs/operators';
13+
import { select, Store, ActionsSubject } from '@ngrx/store';
14+
import { withLatestFrom, filter } from 'rxjs/operators';
1015

1116
import { createTestModule } from './utils';
1217

@@ -134,4 +139,78 @@ describe('Router Store Module', () => {
134139
});
135140
});
136141
});
142+
143+
describe('routerState', () => {
144+
function setup(routerState: RouterState, serializer?: any) {
145+
createTestModule({
146+
reducers: {},
147+
config: {
148+
routerState,
149+
serializer,
150+
},
151+
});
152+
153+
return {
154+
actions: TestBed.get(ActionsSubject) as ActionsSubject,
155+
router: TestBed.get(Router) as Router,
156+
serializer: TestBed.get(RouterStateSerializer) as RouterStateSerializer,
157+
};
158+
}
159+
160+
const onlyRouterActions = (a: any): a is RouterAction<any, any> =>
161+
a.payload && a.payload.event;
162+
163+
describe('Full', () => {
164+
it('should dispatch the full event', async () => {
165+
const { actions, router } = setup(RouterState.Full);
166+
actions
167+
.pipe(filter(onlyRouterActions))
168+
.subscribe(({ payload }) =>
169+
expect(payload.event instanceof RouterEvent).toBe(true)
170+
);
171+
172+
await router.navigateByUrl('/');
173+
});
174+
175+
it('should use the default router serializer', () => {
176+
const { serializer } = setup(RouterState.Full);
177+
expect(serializer).toEqual(new DefaultRouterStateSerializer());
178+
});
179+
180+
it('should use the provided serializer if one is provided', () => {
181+
const { serializer } = setup(
182+
RouterState.Full,
183+
MinimalRouterStateSerializer
184+
);
185+
expect(serializer).toEqual(new MinimalRouterStateSerializer());
186+
});
187+
});
188+
189+
describe('Minimal', () => {
190+
it('should dispatch the navigation id with url', async () => {
191+
const { actions, router } = setup(RouterState.Minimal);
192+
actions
193+
.pipe(filter(onlyRouterActions))
194+
.subscribe(({ payload }: any) => {
195+
expect(payload.event instanceof RouterEvent).toBe(false);
196+
expect(payload.event).toEqual({ id: 1, url: '/' });
197+
});
198+
199+
await router.navigateByUrl('/');
200+
});
201+
202+
it('should use the minimal router serializer', () => {
203+
const { serializer } = setup(RouterState.Minimal);
204+
expect(serializer).toEqual(new MinimalRouterStateSerializer());
205+
});
206+
207+
it('should use the provided serializer if one is provided', () => {
208+
const { serializer } = setup(
209+
RouterState.Minimal,
210+
DefaultRouterStateSerializer
211+
);
212+
expect(serializer).toEqual(new DefaultRouterStateSerializer());
213+
});
214+
});
215+
});
137216
});

modules/router-store/spec/serializer.spec.ts

Lines changed: 0 additions & 101 deletions
This file was deleted.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { RouterStateSnapshot } from '@angular/router';
2+
import {
3+
DefaultRouterStateSerializer,
4+
MinimalRouterStateSerializer,
5+
} from '../src';
6+
7+
describe('default serializer', () => {
8+
it('should serialize all properties', () => {
9+
const serializer = new DefaultRouterStateSerializer();
10+
const snapshot = createRouteSnapshot();
11+
const routerState = {
12+
url: 'url',
13+
root: snapshot,
14+
} as RouterStateSnapshot;
15+
16+
const actual = serializer.serialize(routerState);
17+
const expected = {
18+
url: 'url',
19+
root: createExpectedSnapshot(),
20+
};
21+
expect(actual).toEqual(expected);
22+
});
23+
24+
it('should serialize with an empty routeConfig', () => {
25+
const serializer = new DefaultRouterStateSerializer();
26+
const snapshot = { ...createRouteSnapshot(), routeConfig: null };
27+
const routerState = {
28+
url: 'url',
29+
root: snapshot,
30+
} as RouterStateSnapshot;
31+
32+
const actual = serializer.serialize(routerState);
33+
const expected = {
34+
url: 'url',
35+
root: {
36+
...createExpectedSnapshot(),
37+
routeConfig: null,
38+
component: undefined,
39+
},
40+
};
41+
expect(actual).toEqual(expected);
42+
});
43+
44+
it('should serialize children', () => {
45+
const serializer = new DefaultRouterStateSerializer();
46+
const snapshot = {
47+
...createRouteSnapshot(),
48+
children: [createRouteSnapshot('child')],
49+
};
50+
const routerState = {
51+
url: 'url',
52+
root: snapshot,
53+
} as RouterStateSnapshot;
54+
55+
const actual = serializer.serialize(routerState);
56+
57+
const expected = {
58+
url: 'url',
59+
root: {
60+
...createExpectedSnapshot(),
61+
firstChild: createExpectedSnapshot('child'),
62+
children: [createExpectedSnapshot('child')],
63+
},
64+
};
65+
66+
expect(actual).toEqual(expected);
67+
});
68+
69+
function createExpectedSnapshot(prefix = 'root') {
70+
return {
71+
...createRouteSnapshot(prefix),
72+
component: `${prefix}-route.routeConfig.component`,
73+
root: undefined,
74+
parent: undefined,
75+
firstChild: undefined,
76+
pathFromRoot: undefined,
77+
};
78+
}
79+
});
80+
81+
describe('minimal serializer', () => {
82+
it('should serialize only the minimal properties', () => {
83+
const serializer = new MinimalRouterStateSerializer();
84+
const snapshot = createRouteSnapshot();
85+
const routerState = {
86+
url: 'url',
87+
root: snapshot,
88+
} as RouterStateSnapshot;
89+
90+
const actual = serializer.serialize(routerState);
91+
const expected = {
92+
url: 'url',
93+
root: createExpectedSnapshot(),
94+
};
95+
expect(actual).toEqual(expected);
96+
});
97+
98+
it('should serialize with an empty routeConfig', () => {
99+
const serializer = new MinimalRouterStateSerializer();
100+
const snapshot = { ...createRouteSnapshot(), routeConfig: null };
101+
const routerState = {
102+
url: 'url',
103+
root: snapshot,
104+
} as RouterStateSnapshot;
105+
106+
const actual = serializer.serialize(routerState);
107+
const expected = {
108+
url: 'url',
109+
root: {
110+
...createExpectedSnapshot(),
111+
routeConfig: null,
112+
},
113+
};
114+
expect(actual).toEqual(expected);
115+
});
116+
117+
it('should serialize children', () => {
118+
const serializer = new MinimalRouterStateSerializer();
119+
const snapshot = {
120+
...createRouteSnapshot(),
121+
children: [createRouteSnapshot('child')],
122+
};
123+
const routerState = {
124+
url: 'url',
125+
root: snapshot,
126+
} as RouterStateSnapshot;
127+
128+
const actual = serializer.serialize(routerState);
129+
130+
const expected = {
131+
url: 'url',
132+
root: {
133+
...createExpectedSnapshot(),
134+
firstChild: createExpectedSnapshot('child'),
135+
children: [createExpectedSnapshot('child')],
136+
},
137+
};
138+
139+
expect(actual).toEqual(expected);
140+
});
141+
142+
function createExpectedSnapshot(prefix = 'root') {
143+
let snapshot = {
144+
...createRouteSnapshot(prefix),
145+
routeConfig: {
146+
// config doesn't have a component because it isn't serializable
147+
path: `${prefix}-route.routeConfig.path`,
148+
pathMatch: `${prefix}-route.routeConfig.pathMatch`,
149+
redirectTo: `${prefix}-route.routeConfig.redirectTo`,
150+
outlet: `${prefix}-route.routeConfig.outlet`,
151+
},
152+
firstChild: undefined,
153+
};
154+
155+
// properties that aren't serializable
156+
delete snapshot.paramMap;
157+
delete snapshot.queryParamMap;
158+
delete snapshot.component;
159+
160+
// properties that do not exist on the minimal serializer
161+
delete snapshot.root;
162+
delete snapshot.parent;
163+
delete snapshot.pathFromRoot;
164+
165+
return snapshot;
166+
}
167+
});
168+
169+
function createRouteSnapshot(prefix = 'root'): any {
170+
return {
171+
params: `${prefix}-route.params`,
172+
paramMap: `${prefix}-route.paramMap`,
173+
data: `${prefix}-route.data`,
174+
url: `${prefix}-route.url`,
175+
outlet: `${prefix}-route.outlet`,
176+
routeConfig: {
177+
component: `${prefix}-route.routeConfig.component`,
178+
path: `${prefix}-route.routeConfig.path`,
179+
pathMatch: `${prefix}-route.routeConfig.pathMatch`,
180+
redirectTo: `${prefix}-route.routeConfig.redirectTo`,
181+
outlet: `${prefix}-route.routeConfig.outlet`,
182+
},
183+
queryParams: `${prefix}-route.queryParams`,
184+
queryParamMap: `${prefix}-route.queryParamMap`,
185+
fragment: `${prefix}-route.fragment`,
186+
root: `${prefix}-route.root`,
187+
parent: `${prefix}-route.parent`,
188+
pathFromRoot: `${prefix}-route.params`,
189+
firstChild: null,
190+
children: [],
191+
};
192+
}

0 commit comments

Comments
 (0)