Skip to content

Commit 49b25fd

Browse files
committed
fix(cdk/testing): propagate task state to child environments
When creating a harness via `harnessForFixture`, we await `environment.forceStabilize()` before creating the component harness and its child environment. In newer versions of Safari, resuming from native `await` can escape the test zone back to the root zone. This caused child environments created afterwards to fail the `isInProxyZone()` check and omit `_taskState`, preventing `waitForTasksOutsideAngular` from tracking async tasks scheduled outside Angular. These changes resolve the issue by propagating the task state from the parent `TestbedHarnessEnvironment` down to child environments created via `createEnvironment`.
1 parent 52a1ef3 commit 49b25fd

3 files changed

Lines changed: 13 additions & 10 deletions

File tree

‎goldens/cdk/testing/testbed/index.api.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
import { ComponentFixture } from '@angular/core/testing';
88
import { DirectiveFixture } from '@angular/core/testing';
9+
import { Observable } from 'rxjs';
910

1011
// @public
1112
export type Fixture<T = unknown> = ComponentFixture<T> | DirectiveFixture<T>;
1213

1314
// @public
1415
export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
15-
protected constructor(rawRootElement: Element, _fixture: Fixture, options?: TestbedHarnessEnvironmentOptions);
16+
protected constructor(rawRootElement: Element, _fixture: Fixture, options?: TestbedHarnessEnvironmentOptions, taskState?: Observable<TaskState>);
1617
protected createEnvironment(element: Element): HarnessEnvironment<Element>;
1718
protected createTestElement(element: Element): TestElement;
1819
static documentRootLoader(fixture: Fixture, options?: TestbedHarnessEnvironmentOptions): HarnessLoader;

‎src/cdk/testing/testbed/task-state-zone-interceptor.ts‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,17 @@ type PatchedProxyZone = ProxyZone & {
3030
* This serves as a workaround for https://github.com/angular/angular/issues/32896.
3131
*/
3232
export class TaskStateZoneInterceptor {
33-
private _lastState: HasTaskState | null = null;
34-
3533
/** Subject that can be used to emit a new state change. */
36-
private readonly _stateSubject = new BehaviorSubject<TaskState>(
37-
this._lastState ? this._getTaskStateFromInternalZoneState(this._lastState) : {stable: true},
38-
);
34+
private readonly _stateSubject: BehaviorSubject<TaskState>;
3935

4036
/** Public observable that emits whenever the task state changes. */
41-
readonly state: Observable<TaskState> = this._stateSubject;
37+
readonly state: Observable<TaskState>;
4238

4339
constructor(lastState: HasTaskState | null) {
44-
this._lastState = lastState;
40+
this._stateSubject = new BehaviorSubject<TaskState>(
41+
lastState ? this._getTaskStateFromInternalZoneState(lastState) : {stable: true},
42+
);
43+
this.state = this._stateSubject;
4544
}
4645

4746
/** This will be called whenever the task state changes in the intercepted zone. */

‎src/cdk/testing/testbed/testbed-harness-environment.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,13 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
106106
rawRootElement: Element,
107107
private _fixture: Fixture,
108108
options?: TestbedHarnessEnvironmentOptions,
109+
taskState?: Observable<TaskState>,
109110
) {
110111
super(rawRootElement);
111112
this._options = {...defaultEnvironmentOptions, ...options};
112-
if (TaskStateZoneInterceptor.isInProxyZone()) {
113+
if (taskState) {
114+
this._taskState = taskState;
115+
} else if (TaskStateZoneInterceptor.isInProxyZone()) {
113116
this._taskState = TaskStateZoneInterceptor.setup();
114117
}
115118
this._stabilizeCallback = () => this.forceStabilize();
@@ -219,7 +222,7 @@ export class TestbedHarnessEnvironment extends HarnessEnvironment<Element> {
219222

220223
/** Creates a `HarnessLoader` rooted at the given raw element. */
221224
protected createEnvironment(element: Element): HarnessEnvironment<Element> {
222-
return new TestbedHarnessEnvironment(element, this._fixture, this._options);
225+
return new TestbedHarnessEnvironment(element, this._fixture, this._options, this._taskState);
223226
}
224227

225228
/**

0 commit comments

Comments
 (0)