Skip to content

TestBed should be zoneless compatible #48198

@yjaaidi

Description

@yjaaidi

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

TL;DR: TestBed should provide a way to run zoneless and avoid importing zone.js when we don't need it.
And I'd love to help with a PR?

TestBed assumes that zone.js is available while there are contexts when this is not necessary and here are some examples:

  • zoneless apps & libs
  • tests that do not depend on change detection: service tests, pipe tests, "isolated" component testing etc...
  • tests where CD is triggered manually using fixture.detectChanges()

These tests must load zone.js when they don't need it.
While this might sound like a really minor issue, loading zone.js can cause trouble in some situations.

For instance, integrating TestBed and zone.js with vitest causes the following error Method Promise.prototype.then called on incompatible receiver which is probably due to zone.js patching promises and breaking Node.js's safe promises when importing ESMs dynamically or something like that. This is similar to the issue described here #47872.

Proposed solution

A first quick win is replacing this:

const ngZone = new NgZone({enableLongStackTrace: true});
const providers: Provider[] = [
{provide: NgZone, useValue: ngZone},

with:

{provide: NgZone, useFactory: () => new NgZone({enableLongStackTrace: true}); }

this would then allow us to go zoneless with this configuration:

TestBed.configureTestingModule({
  providers: [
    {
      provide: NgZone,
      useClass: ɵNoopNgZone,
    },
  ],
});

The main problem with this approach is the boilerplate and having to use the ɵNoopNgZone implementation detail.

A second step would be adding the bootstrap's ngZone option to initTestEnvironment:

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  {ngZone: 'noop'}
);

Alternatives considered

Disable promises monkey patching using globalThis.__Zone_disable_ZoneAwarePromise = true
but this causes the following issue #37349
Cf. #48359

Metadata

Metadata

Assignees

Labels

area: coreIssues related to the framework runtimearea: testingIssues related to Angular testing features, such as TestBedarea: zonesIssues related to zone.js

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions