jest-preset-angular icon indicating copy to clipboard operation
jest-preset-angular copied to clipboard

Angular: Jest without Zone (noNgZone).

Open x47188 opened this issue 5 years ago • 15 comments

Hey 🙌

I was wondering if there was any documented way to run Angular 9 + Jest without zone.js ( setupJest.ts heavily relies on Zone)?

x47188 avatar Feb 29 '20 22:02 x47188

Hey!

No, we just got into the first compatibility issues with Angular 9, so there's no work done on this field so far. But you can try removing these imports in your project and report your findings!

wtho avatar Mar 02 '20 22:03 wtho

Removing the zone imports will raise an In this configuration Angular requires Zone.js error at boot.

Some interesting findings:

  • I'm not getting a TestBedRender3 instance from getTestBed() (probably related to the fact that I'm not using ngcc-compiled Ivy bundles).

  • Nothing is available inside current TestBedViewEngine or TestBedRender3 implementations to easily disable Zone.js (that noNgZone flag could be a potential answer though).

  • I tried toying with the injection container replacing NgZone value with a NoopNgZone etc... without success.

ghost avatar Mar 02 '20 22:03 ghost

I remember I tried this before, with Angular 8 or lower I also got some similar errors so I gave up about excluding zone. Angular looks like tightly coupled with zone

ahnpnl avatar Mar 03 '20 07:03 ahnpnl

@x47188 but if I interpret the issue right, you do have an app that runs without zone.js and you want to achieve the same in jsdom for jest, is that the case? Then I think we should look into it.

wtho avatar Mar 03 '20 07:03 wtho

but if I interpret the issue right, you do have an app that runs without zone.js and you want to achieve the same in jsdom for jest, is that the case?

Absolutely.

Then I think we should look into it.

Very appreciated!

However I fear the current TestBedRender3 implementation isn't flexible enough to allow ivy-only zonejs-less rendering.

ghost avatar Mar 04 '20 18:03 ghost

Do your zoneless tests run in Karma?

wtho avatar Mar 13 '20 07:03 wtho

@wtho good question, I'll create a "repro" to verify that. (I've striped karma & co from my current code-base)

ghost avatar Mar 25 '20 16:03 ghost

Thanks, if you could also share it, that would be awesome!

wtho avatar Mar 25 '20 17:03 wtho

I think this depends on the development from Angular to work without zone, which is currently in roadmap https://angular.io/guide/roadmap#leverage-full-framework-capabilities-with-zonejs-opt-out

ahnpnl avatar Dec 01 '20 21:12 ahnpnl

@ahnpnl Hi, since angular 18 features experimental zoneless support, is that planned for the near future? Right now in the application without zone, importing preset with import 'jest-preset-angular/setup-jest'; throws an error, since zone is not loaded in zoneless application.

Cannot find module 'zone.js' from 'node_modules/jest-preset-angular/setup-jest.js'

igorzablotny avatar May 24 '24 09:05 igorzablotny

Hi, yes I think if we can rely on a flag from angular package to detect when zone is available to import, it should be easy to implement into the existing setup file.

If there is no such flag, i think we might need a separate setup file for testing zoneless application.

PR is welcome :)

ahnpnl avatar May 24 '24 10:05 ahnpnl

This currently is a blocker for us to start using Zoneless apps in Angular 18. Would love to see a fix :bow:

meierw avatar Jun 01 '24 14:06 meierw

You can simply copy the content of setup-jest.js and remove zone import.

ahnpnl avatar Jun 01 '24 14:06 ahnpnl

Ok it was a bit of an ordeal that I had to go through. Cause I was using @angular-builders/jest.

Even though I understood from the docs that @angular-builders/jest merges it's config with the user config. I still couldn't get all the correct config values to work and overwrite the base config that @angular-builders/jest had under the hood.

In the end I completely ripped out @angular-builders/jest in favor of just using jest directly.

Now my jest config looks like this and works with provideExperimentalZonelessChangeDetection() everywhere. In my app config as well as in my TestBed providers.

// package.json
{  
  "jest": {
    "preset": "jest-preset-angular",
    "setupFilesAfterEnv": [
      "<rootDir>/jest.setup.ts"
    ]
  }
}
// jest.setup.ts
import { getTestBed } from "@angular/core/testing"
import {
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting,
} from "@angular/platform-browser-dynamic/testing"

const testEnvironmentOptions =
  (globalThis as any).ngJest?.testEnvironmentOptions ?? Object.create(null)

getTestBed().initTestEnvironment(
  BrowserDynamicTestingModule,
  platformBrowserDynamicTesting(),
  testEnvironmentOptions,
)

Thanks. @ahnpnl for the hint of just copying the setup code.

meierw avatar Jun 01 '24 20:06 meierw

Besides, I asked Angular team and they also suggested to include this https://github.com/angular/components/blob/04d3b63de2fb843beb55836e39e930c3342d26f1/test/angular-test-init-spec.ts#L35

I think in the next major release, we can provide function to call instead of implicitly calling setup TestBed upon import like current way.

Providing function call to setup Jest will be more flexible instead of relying on globalThis

ahnpnl avatar Jun 02 '24 12:06 ahnpnl