Skip to content

Commit 0b6084e

Browse files
atscottAndrewKushnir
authored andcommitted
refactor(router): split remainder of describes in integration test file (angular#60313)
to more easily navigate and identify different suites of integration tests, this commit splits them into several different files PR Close angular#60313
1 parent 0a9403e commit 0b6084e

File tree

5 files changed

+1608
-1483
lines changed

5 files changed

+1608
-1483
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import {Injectable, inject as coreInject} from '@angular/core';
10+
import {Location} from '@angular/common';
11+
import {TestBed, fakeAsync, tick} from '@angular/core/testing';
12+
import {
13+
Router,
14+
ActivatedRouteSnapshot,
15+
RouterStateSnapshot,
16+
provideRouter,
17+
withRouterConfig,
18+
NavigationStart,
19+
GuardsCheckEnd,
20+
} from '@angular/router/src';
21+
import {createRoot, SimpleCmp, advance, RootCmp, BlankCmp} from './integration_helpers';
22+
23+
export function duplicateInFlightNavigationsIntegrationSuite() {
24+
describe('duplicate in-flight navigations', () => {
25+
@Injectable()
26+
class RedirectingGuard {
27+
skipLocationChange = false;
28+
constructor(private router: Router) {}
29+
canActivate() {
30+
this.router.navigate(['/simple'], {skipLocationChange: this.skipLocationChange});
31+
return false;
32+
}
33+
}
34+
35+
beforeEach(() => {
36+
TestBed.configureTestingModule({
37+
providers: [
38+
{
39+
provide: 'in1Second',
40+
useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
41+
let res: any = null;
42+
const p = new Promise((_) => (res = _));
43+
setTimeout(() => res(true), 1000);
44+
return p;
45+
},
46+
},
47+
RedirectingGuard,
48+
],
49+
});
50+
});
51+
52+
it('should reset location if a navigation by location is successful', fakeAsync(() => {
53+
const router = TestBed.inject(Router);
54+
const location = TestBed.inject(Location);
55+
const fixture = createRoot(router, RootCmp);
56+
57+
router.resetConfig([{path: 'simple', component: SimpleCmp, canActivate: ['in1Second']}]);
58+
59+
// Trigger two location changes to the same URL.
60+
// Because of the guard the order will look as follows:
61+
// - location change 'simple'
62+
// - start processing the change, start a guard
63+
// - location change 'simple'
64+
// - the first location change gets canceled, the URL gets reset to '/'
65+
// - the second location change gets finished, the URL should be reset to '/simple'
66+
location.go('/simple');
67+
location.historyGo(0);
68+
location.historyGo(0);
69+
70+
tick(2000);
71+
advance(fixture);
72+
73+
expect(location.path()).toEqual('/simple');
74+
}));
75+
76+
it('should skip duplicate location events', fakeAsync(() => {
77+
const router = TestBed.inject(Router);
78+
const location = TestBed.inject(Location);
79+
const fixture = createRoot(router, RootCmp);
80+
81+
router.resetConfig([
82+
{
83+
path: 'blocked',
84+
component: BlankCmp,
85+
canActivate: [() => coreInject(RedirectingGuard).canActivate()],
86+
},
87+
{path: 'simple', component: SimpleCmp},
88+
]);
89+
router.navigateByUrl('/simple');
90+
advance(fixture);
91+
92+
location.go('/blocked');
93+
location.historyGo(0);
94+
95+
advance(fixture);
96+
expect(fixture.nativeElement.innerHTML).toContain('simple');
97+
}));
98+
99+
it('should not cause URL thrashing', async () => {
100+
TestBed.configureTestingModule({
101+
providers: [provideRouter([], withRouterConfig({urlUpdateStrategy: 'eager'}))],
102+
});
103+
104+
const router = TestBed.inject(Router);
105+
const location = TestBed.inject(Location);
106+
const fixture = TestBed.createComponent(RootCmp);
107+
fixture.detectChanges();
108+
109+
router.resetConfig([
110+
{path: 'home', component: SimpleCmp},
111+
{
112+
path: 'blocked',
113+
component: BlankCmp,
114+
canActivate: [() => coreInject(RedirectingGuard).canActivate()],
115+
},
116+
{path: 'simple', component: SimpleCmp},
117+
]);
118+
119+
await router.navigateByUrl('/home');
120+
const urlChanges: string[] = [];
121+
location.onUrlChange((change) => {
122+
urlChanges.push(change);
123+
});
124+
125+
await router.navigateByUrl('/blocked');
126+
await fixture.whenStable();
127+
128+
expect(fixture.nativeElement.innerHTML).toContain('simple');
129+
// We do not want the URL to flicker to `/home` between the /blocked and /simple routes
130+
expect(urlChanges).toEqual(['/blocked', '/simple']);
131+
});
132+
133+
it('can render a 404 page without changing the URL', fakeAsync(() => {
134+
TestBed.configureTestingModule({
135+
providers: [provideRouter([], withRouterConfig({urlUpdateStrategy: 'eager'}))],
136+
});
137+
const router = TestBed.inject(Router);
138+
TestBed.inject(RedirectingGuard).skipLocationChange = true;
139+
const location = TestBed.inject(Location);
140+
const fixture = createRoot(router, RootCmp);
141+
142+
router.resetConfig([
143+
{path: 'home', component: SimpleCmp},
144+
{
145+
path: 'blocked',
146+
component: BlankCmp,
147+
canActivate: [() => coreInject(RedirectingGuard).canActivate()],
148+
},
149+
{path: 'simple', redirectTo: '404'},
150+
{path: '404', component: SimpleCmp},
151+
]);
152+
router.navigateByUrl('/home');
153+
advance(fixture);
154+
155+
location.go('/blocked');
156+
location.historyGo(0);
157+
advance(fixture);
158+
expect(location.path()).toEqual('/blocked');
159+
expect(fixture.nativeElement.innerHTML).toContain('simple');
160+
}));
161+
162+
it('should accurately track currentNavigation', fakeAsync(() => {
163+
const router = TestBed.inject(Router);
164+
router.resetConfig([
165+
{path: 'one', component: SimpleCmp, canActivate: ['in1Second']},
166+
{path: 'two', component: BlankCmp, canActivate: ['in1Second']},
167+
]);
168+
169+
router.events.subscribe((e) => {
170+
if (e instanceof NavigationStart) {
171+
if (e.url === '/one') {
172+
router.navigateByUrl('two');
173+
}
174+
router.events.subscribe((e) => {
175+
if (e instanceof GuardsCheckEnd) {
176+
expect(router.getCurrentNavigation()?.extractedUrl.toString()).toEqual('/two');
177+
expect(router.getCurrentNavigation()?.extras).toBeDefined();
178+
}
179+
});
180+
}
181+
});
182+
183+
router.navigateByUrl('one');
184+
tick(1000);
185+
}));
186+
});
187+
}

0 commit comments

Comments
 (0)