@@ -32,6 +32,10 @@ import {DeferBlockFixture} from './defer';
3232import { ComponentFixtureAutoDetect , ComponentFixtureNoNgZone } from './test_bed_common' ;
3333import { TestBedApplicationErrorHandler } from './application_error_handler' ;
3434
35+ interface TestAppRef {
36+ externalTestViews : Set < ViewRef > ;
37+ }
38+
3539/**
3640 * Fixture for debugging and testing a component.
3741 *
@@ -79,14 +83,14 @@ export abstract class ComponentFixture<T> {
7983 // behavior.
8084 /** @internal */
8185 protected readonly _appRef = inject ( ApplicationRef ) ;
82- /** @internal */
83- protected readonly _testAppRef = this . _appRef as unknown as TestAppRef ;
86+ private readonly _testAppRef = this . _appRef as unknown as TestAppRef ;
8487 private readonly pendingTasks = inject ( PendingTasks ) ;
8588 private readonly appErrorHandler = inject ( TestBedApplicationErrorHandler ) ;
8689 /** @internal */
8790 protected abstract _autoDetect : boolean ;
8891 private readonly scheduler = inject ( ɵChangeDetectionScheduler , { optional : true } ) ;
8992 private readonly zonelessEnabled = inject ( ZONELESS_ENABLED ) ;
93+ private subscriptions = new Subscription ( ) ;
9094
9195 // TODO(atscott): Remove this from public API
9296 ngZone = this . _noZoneOptionIsSet ? null : this . _ngZone ;
@@ -111,6 +115,17 @@ export abstract class ComponentFixture<T> {
111115 this . componentRef . hostView . onDestroy ( ( ) => {
112116 this . _testAppRef . externalTestViews . delete ( this . componentRef . hostView ) ;
113117 } ) ;
118+ // Create subscriptions outside the NgZone so that the callbacks run outside
119+ // of NgZone.
120+ this . _ngZone . runOutsideAngular ( ( ) => {
121+ this . subscriptions . add (
122+ this . _ngZone . onError . subscribe ( {
123+ next : ( error : any ) => {
124+ throw error ;
125+ } ,
126+ } ) ,
127+ ) ;
128+ } ) ;
114129 }
115130
116131 /**
@@ -213,6 +228,7 @@ export abstract class ComponentFixture<T> {
213228 * Trigger component destruction.
214229 */
215230 destroy ( ) : void {
231+ this . subscriptions . unsubscribe ( ) ;
216232 this . _testAppRef . externalTestViews . delete ( this . componentRef . hostView ) ;
217233 if ( ! this . _isDestroyed ) {
218234 this . componentRef . destroy ( ) ;
@@ -244,33 +260,13 @@ export class ScheduledComponentFixture<T> extends ComponentFixture<T> {
244260 }
245261}
246262
247- interface TestAppRef {
248- externalTestViews : Set < ViewRef > ;
249- }
250-
251263/**
252264 * ComponentFixture behavior that attempts to act as a "mini application".
253265 */
254266export class PseudoApplicationComponentFixture < T > extends ComponentFixture < T > {
255- private _subscriptions = new Subscription ( ) ;
256267 /** @internal */
257268 override _autoDetect = inject ( ComponentFixtureAutoDetect , { optional : true } ) ?? false ;
258269
259- override initialize ( ) : void {
260- super . initialize ( ) ;
261- // Create subscriptions outside the NgZone so that the callbacks run outside
262- // of NgZone.
263- this . _ngZone . runOutsideAngular ( ( ) => {
264- this . _subscriptions . add (
265- this . _ngZone . onError . subscribe ( {
266- next : ( error : any ) => {
267- throw error ;
268- } ,
269- } ) ,
270- ) ;
271- } ) ;
272- }
273-
274270 override detectChanges ( checkNoChanges = true ) : void {
275271 this . _effectRunner . flush ( ) ;
276272 // Run the change detection inside the NgZone so that any async tasks as part of the change
@@ -285,9 +281,4 @@ export class PseudoApplicationComponentFixture<T> extends ComponentFixture<T> {
285281 // dirty in response to input signals changing.
286282 this . _effectRunner . flush ( ) ;
287283 }
288-
289- override destroy ( ) : void {
290- this . _subscriptions . unsubscribe ( ) ;
291- super . destroy ( ) ;
292- }
293284}
0 commit comments