Skip to content

Commit 4356e85

Browse files
committed
fix(core): fakeAsync should not depend on module import order (angular#61375)
`fakeAsync` does not work if the zone-testing polyfill is included after @angular/core/testing is loaded. This allows fakeAsync to work even if the zone-testing is included later. PR Close angular#61375
1 parent e33444e commit 4356e85

File tree

1 file changed

+19
-29
lines changed

1 file changed

+19
-29
lines changed

packages/core/testing/src/fake_async.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@
1010
import type {} from 'zone.js';
1111

1212
const _Zone: any = typeof Zone !== 'undefined' ? Zone : null;
13-
const fakeAsyncTestModule = _Zone && _Zone[_Zone.__symbol__('fakeAsyncTest')];
13+
function getFakeAsyncTestModule() {
14+
return _Zone && _Zone[_Zone.__symbol__('fakeAsyncTest')];
15+
}
1416

15-
const fakeAsyncTestModuleNotLoadedErrorMessage = `zone-testing.js is needed for the fakeAsync() test helper but could not be found.
16-
Please make sure that your environment includes zone.js/testing`;
17+
function withFakeAsyncTestModule(fn: (fakeAsyncTestModule: any) => any): any {
18+
const fakeAsyncTestModule = getFakeAsyncTestModule();
19+
if (!fakeAsyncTestModule) {
20+
throw new Error(`zone-testing.js is needed for the fakeAsync() test helper but could not be found.
21+
Please make sure that your environment includes zone.js/testing`);
22+
}
23+
return fn(fakeAsyncTestModule);
24+
}
1725

1826
/**
1927
* Clears out the shared fake async zone for a test.
@@ -22,15 +30,12 @@ const fakeAsyncTestModuleNotLoadedErrorMessage = `zone-testing.js is needed for
2230
* @publicApi
2331
*/
2432
export function resetFakeAsyncZone(): void {
25-
if (fakeAsyncTestModule) {
26-
return fakeAsyncTestModule.resetFakeAsyncZone();
27-
}
28-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
33+
withFakeAsyncTestModule((v) => v.resetFakeAsyncZone());
2934
}
3035

3136
export function resetFakeAsyncZoneIfExists(): void {
32-
if (fakeAsyncTestModule && (Zone as any)['ProxyZoneSpec']?.isLoaded()) {
33-
fakeAsyncTestModule.resetFakeAsyncZone();
37+
if (getFakeAsyncTestModule() && (Zone as any)['ProxyZoneSpec']?.isLoaded()) {
38+
getFakeAsyncTestModule().resetFakeAsyncZone();
3439
}
3540
}
3641

@@ -59,10 +64,7 @@ export function resetFakeAsyncZoneIfExists(): void {
5964
* @publicApi
6065
*/
6166
export function fakeAsync(fn: Function, options?: {flush?: boolean}): (...args: any[]) => any {
62-
if (fakeAsyncTestModule) {
63-
return fakeAsyncTestModule.fakeAsync(fn, options);
64-
}
65-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
67+
return withFakeAsyncTestModule((v) => v.fakeAsync(fn, options));
6668
}
6769

6870
/**
@@ -135,10 +137,7 @@ export function tick(
135137
processNewMacroTasksSynchronously: true,
136138
},
137139
): void {
138-
if (fakeAsyncTestModule) {
139-
return fakeAsyncTestModule.tick(millis, tickOptions);
140-
}
141-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
140+
return withFakeAsyncTestModule((m) => m.tick(millis, tickOptions));
142141
}
143142

144143
/**
@@ -153,10 +152,7 @@ export function tick(
153152
* @publicApi
154153
*/
155154
export function flush(maxTurns?: number): number {
156-
if (fakeAsyncTestModule) {
157-
return fakeAsyncTestModule.flush(maxTurns);
158-
}
159-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
155+
return withFakeAsyncTestModule((m) => m.flush(maxTurns));
160156
}
161157

162158
/**
@@ -165,10 +161,7 @@ export function flush(maxTurns?: number): number {
165161
* @publicApi
166162
*/
167163
export function discardPeriodicTasks(): void {
168-
if (fakeAsyncTestModule) {
169-
return fakeAsyncTestModule.discardPeriodicTasks();
170-
}
171-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
164+
return withFakeAsyncTestModule((m) => m.discardPeriodicTasks());
172165
}
173166

174167
/**
@@ -177,8 +170,5 @@ export function discardPeriodicTasks(): void {
177170
* @publicApi
178171
*/
179172
export function flushMicrotasks(): void {
180-
if (fakeAsyncTestModule) {
181-
return fakeAsyncTestModule.flushMicrotasks();
182-
}
183-
throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
173+
return withFakeAsyncTestModule((m) => m.flushMicrotasks());
184174
}

0 commit comments

Comments
 (0)