6
6
* found in the LICENSE file at https://angular.dev/license
7
7
*/
8
8
9
- import { Inject , Injectable , InjectionToken } from '../di' ;
9
+ import { inject , Inject , Injectable , InjectionToken } from '../di' ;
10
+ import { isInInjectionContext } from '../di/contextual' ;
11
+ import { DestroyRef } from '../linker/destroy_ref' ;
10
12
import { NgZone } from '../zone/ng_zone' ;
11
13
12
14
/**
@@ -84,13 +86,21 @@ export class Testability implements PublicTestability {
84
86
private _isZoneStable : boolean = true ;
85
87
private _callbacks : WaitCallback [ ] = [ ] ;
86
88
87
- private taskTrackingZone : { macroTasks : Task [ ] } | null = null ;
89
+ private _taskTrackingZone : { macroTasks : Task [ ] } | null = null ;
90
+
91
+ private _destroyRef ?: DestroyRef ;
88
92
89
93
constructor (
90
94
private _ngZone : NgZone ,
91
95
private registry : TestabilityRegistry ,
92
96
@Inject ( TESTABILITY_GETTER ) testabilityGetter : GetTestability ,
93
97
) {
98
+ // Attempt to retrieve a `DestroyRef` optionally.
99
+ // For backwards compatibility reasons, this cannot be required.
100
+ if ( isInInjectionContext ( ) ) {
101
+ this . _destroyRef = inject ( DestroyRef , { optional : true } ) ?? undefined ;
102
+ }
103
+
94
104
// If there was no Testability logic registered in the global scope
95
105
// before, register the current testability getter as a global one.
96
106
if ( ! _testabilityGetter ) {
@@ -99,19 +109,19 @@ export class Testability implements PublicTestability {
99
109
}
100
110
this . _watchAngularEvents ( ) ;
101
111
_ngZone . run ( ( ) => {
102
- this . taskTrackingZone =
112
+ this . _taskTrackingZone =
103
113
typeof Zone == 'undefined' ? null : Zone . current . get ( 'TaskTrackingZone' ) ;
104
114
} ) ;
105
115
}
106
116
107
117
private _watchAngularEvents ( ) : void {
108
- this . _ngZone . onUnstable . subscribe ( {
118
+ const onUnstableSubscription = this . _ngZone . onUnstable . subscribe ( {
109
119
next : ( ) => {
110
120
this . _isZoneStable = false ;
111
121
} ,
112
122
} ) ;
113
123
114
- this . _ngZone . runOutsideAngular ( ( ) => {
124
+ const onStableSubscription = this . _ngZone . runOutsideAngular ( ( ) =>
115
125
this . _ngZone . onStable . subscribe ( {
116
126
next : ( ) => {
117
127
NgZone . assertNotInAngularZone ( ) ;
@@ -120,7 +130,12 @@ export class Testability implements PublicTestability {
120
130
this . _runCallbacksIfReady ( ) ;
121
131
} ) ;
122
132
} ,
123
- } ) ;
133
+ } ) ,
134
+ ) ;
135
+
136
+ this . _destroyRef ?. onDestroy ( ( ) => {
137
+ onUnstableSubscription . unsubscribe ( ) ;
138
+ onStableSubscription . unsubscribe ( ) ;
124
139
} ) ;
125
140
}
126
141
@@ -156,12 +171,12 @@ export class Testability implements PublicTestability {
156
171
}
157
172
158
173
private getPendingTasks ( ) : PendingMacrotask [ ] {
159
- if ( ! this . taskTrackingZone ) {
174
+ if ( ! this . _taskTrackingZone ) {
160
175
return [ ] ;
161
176
}
162
177
163
178
// Copy the tasks data so that we don't leak tasks.
164
- return this . taskTrackingZone . macroTasks . map ( ( t : Task ) => {
179
+ return this . _taskTrackingZone . macroTasks . map ( ( t : Task ) => {
165
180
return {
166
181
source : t . source ,
167
182
// From TaskTrackingZone:
@@ -196,7 +211,7 @@ export class Testability implements PublicTestability {
196
211
* and no further updates will be issued.
197
212
*/
198
213
whenStable ( doneCb : Function , timeout ?: number , updateCb ?: Function ) : void {
199
- if ( updateCb && ! this . taskTrackingZone ) {
214
+ if ( updateCb && ! this . _taskTrackingZone ) {
200
215
throw new Error (
201
216
'Task tracking zone is required when passing an update callback to ' +
202
217
'whenStable(). Is "zone.js/plugins/task-tracking" loaded?' ,
0 commit comments