diff --git a/.editorconfig b/.editorconfig
index 8bed5ad4df..45c01ff049 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -19,7 +19,7 @@ tab_width = 4
[*.{yml, yaml}]
indent_size = 2
-[*.{js,jsx,ts,tsx}]
+[*.{js,jsx,ts,tsx,mjs,mjsx,tsx,mtsx}]
indent_size = 4
[*.html]
diff --git a/e2e/zoneless-env/__tests__/zoneless-env.spec.ts b/e2e/zoneless-env/__tests__/zoneless-env.spec.ts
new file mode 100644
index 0000000000..ea305d8c1b
--- /dev/null
+++ b/e2e/zoneless-env/__tests__/zoneless-env.spec.ts
@@ -0,0 +1,18 @@
+import { TestBed } from '@angular/core/testing';
+
+import { FooComponent } from '../foo.component';
+
+describe('FooComponent', () => {
+ it('should trigger change detection without fixture.detectChanges', () => {
+ TestBed.configureTestingModule({
+ imports: [FooComponent],
+ });
+ const fixture = TestBed.createComponent(FooComponent);
+
+ expect(fixture.componentInstance.value1()).toBe('val1');
+
+ fixture.componentRef.setInput('value1', 'hello');
+
+ expect(fixture.componentInstance.value1()).toBe('hello');
+ });
+});
diff --git a/e2e/zoneless-env/foo.component.html b/e2e/zoneless-env/foo.component.html
new file mode 100644
index 0000000000..cdd69d0efa
--- /dev/null
+++ b/e2e/zoneless-env/foo.component.html
@@ -0,0 +1,10 @@
+
+
Line 1
+
+
+ {{ value1() }}
+
+
+ {{ value2() }}
+
+
diff --git a/e2e/zoneless-env/foo.component.scss b/e2e/zoneless-env/foo.component.scss
new file mode 100644
index 0000000000..c2393c27c0
--- /dev/null
+++ b/e2e/zoneless-env/foo.component.scss
@@ -0,0 +1,3 @@
+p {
+ font-size: 1.6rem;
+}
diff --git a/e2e/zoneless-env/foo.component.ts b/e2e/zoneless-env/foo.component.ts
new file mode 100644
index 0000000000..62407aed74
--- /dev/null
+++ b/e2e/zoneless-env/foo.component.ts
@@ -0,0 +1,25 @@
+import { NgIf } from '@angular/common';
+import { Component, input } from '@angular/core';
+
+@Component({
+ selector: 'foo',
+ standalone: true,
+ templateUrl: './foo.component.html',
+ styleUrls: ['./foo.component.scss'],
+ // we have to setup styles this way, since simple styles/styleUrs properties will be removed (jest does not unit test styles)
+ styles: [
+ `
+ p {
+ color: red;
+ }
+ `,
+ ],
+ imports: [NgIf],
+})
+export class FooComponent {
+ readonly value1 = input('val1');
+ readonly value2 = input('val2');
+
+ protected readonly condition1 = true;
+ protected readonly condition2 = false;
+}
diff --git a/e2e/zoneless-env/jest-cjs.config.ts b/e2e/zoneless-env/jest-cjs.config.ts
new file mode 100644
index 0000000000..13b7970b6e
--- /dev/null
+++ b/e2e/zoneless-env/jest-cjs.config.ts
@@ -0,0 +1,24 @@
+import type { JestConfigWithTsJest } from 'ts-jest';
+
+const config: JestConfigWithTsJest = {
+ displayName: 'e2e-zoneless-env',
+ testEnvironment: 'jsdom',
+ snapshotSerializers: [
+ '/../../build/serializers/html-comment',
+ '/../../build/serializers/ng-snapshot',
+ '/../../build/serializers/no-ng-attributes',
+ ],
+ setupFilesAfterEnv: ['./setup-zoneless-env.ts'],
+ transform: {
+ '^.+\\.(ts|js|mjs|html)$': [
+ '/../../build/index.js',
+ {
+ tsconfig: '/tsconfig-cjs.spec.json',
+ stringifyContentPathRegex: '\\.(html|svg)$',
+ },
+ ],
+ },
+ transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
+};
+
+export default config;
diff --git a/e2e/zoneless-env/jest-esm.config.ts b/e2e/zoneless-env/jest-esm.config.ts
new file mode 100644
index 0000000000..c521da99eb
--- /dev/null
+++ b/e2e/zoneless-env/jest-esm.config.ts
@@ -0,0 +1,28 @@
+import type { JestConfigWithTsJest } from 'ts-jest';
+
+const config: JestConfigWithTsJest = {
+ displayName: 'e2e-zoneless-env',
+ testEnvironment: 'jsdom',
+ snapshotSerializers: [
+ '/../../build/serializers/html-comment',
+ '/../../build/serializers/ng-snapshot',
+ '/../../build/serializers/no-ng-attributes',
+ ],
+ setupFilesAfterEnv: ['./setup-zoneless-env.mts'],
+ moduleNameMapper: {
+ rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js',
+ },
+ extensionsToTreatAsEsm: ['.ts', '.mts'],
+ transform: {
+ '^.+\\.(ts|mts|js|mjs|html)$': [
+ '/../../build/index.js',
+ {
+ useESM: true,
+ tsconfig: '/tsconfig-esm.spec.json',
+ stringifyContentPathRegex: '\\.(html|svg)$',
+ },
+ ],
+ },
+};
+
+export default config;
diff --git a/e2e/zoneless-env/jest-transpile-cjs.config.ts b/e2e/zoneless-env/jest-transpile-cjs.config.ts
new file mode 100644
index 0000000000..46d6084eee
--- /dev/null
+++ b/e2e/zoneless-env/jest-transpile-cjs.config.ts
@@ -0,0 +1,25 @@
+import type { JestConfigWithTsJest } from 'ts-jest';
+
+const config: JestConfigWithTsJest = {
+ displayName: 'e2e-snapshot-serializers',
+ testEnvironment: 'jsdom',
+ snapshotSerializers: [
+ '/../../build/serializers/html-comment',
+ '/../../build/serializers/ng-snapshot',
+ '/../../build/serializers/no-ng-attributes',
+ ],
+ setupFilesAfterEnv: ['./setup-zoneless-env.ts'],
+ transform: {
+ '^.+\\.(ts|js|mjs|html)$': [
+ '/../../build/index.js',
+ {
+ tsconfig: '/tsconfig-cjs.spec.json',
+ stringifyContentPathRegex: '\\.(html|svg)$',
+ isolatedModules: true,
+ },
+ ],
+ },
+ transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
+};
+
+export default config;
diff --git a/e2e/zoneless-env/jest-transpile-esm.config.ts b/e2e/zoneless-env/jest-transpile-esm.config.ts
new file mode 100644
index 0000000000..1e57840617
--- /dev/null
+++ b/e2e/zoneless-env/jest-transpile-esm.config.ts
@@ -0,0 +1,29 @@
+import type { JestConfigWithTsJest } from 'ts-jest';
+
+const config: JestConfigWithTsJest = {
+ displayName: 'e2e-snapshot-serializers',
+ testEnvironment: 'jsdom',
+ snapshotSerializers: [
+ '/../../build/serializers/html-comment',
+ '/../../build/serializers/ng-snapshot',
+ '/../../build/serializers/no-ng-attributes',
+ ],
+ setupFilesAfterEnv: ['./setup-zoneless-env.mts'],
+ moduleNameMapper: {
+ rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js',
+ },
+ extensionsToTreatAsEsm: ['.ts', '.mts'],
+ transform: {
+ '^.+\\.(ts|mts|js|mjs|html)$': [
+ '/../../build/index.js',
+ {
+ useESM: true,
+ tsconfig: '/tsconfig-esm.spec.json',
+ stringifyContentPathRegex: '\\.(html|svg)$',
+ isolatedModules: true,
+ },
+ ],
+ },
+};
+
+export default config;
diff --git a/e2e/zoneless-env/setup-zoneless-env.mts b/e2e/zoneless-env/setup-zoneless-env.mts
new file mode 100644
index 0000000000..6375b3715a
--- /dev/null
+++ b/e2e/zoneless-env/setup-zoneless-env.mts
@@ -0,0 +1,3 @@
+import { setupZonelessTestEnv } from '../../setup-env/zoneless/index.mjs';
+
+setupZonelessTestEnv();
diff --git a/e2e/zoneless-env/setup-zoneless-env.ts b/e2e/zoneless-env/setup-zoneless-env.ts
new file mode 100644
index 0000000000..b16ec598be
--- /dev/null
+++ b/e2e/zoneless-env/setup-zoneless-env.ts
@@ -0,0 +1,3 @@
+import { setupZonelessTestEnv } from '../../setup-env/zoneless';
+
+setupZonelessTestEnv();
diff --git a/e2e/zoneless-env/tsconfig-cjs.spec.json b/e2e/zoneless-env/tsconfig-cjs.spec.json
new file mode 100644
index 0000000000..f65fc7b4f1
--- /dev/null
+++ b/e2e/zoneless-env/tsconfig-cjs.spec.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../../tsconfig-base.spec.json"
+}
diff --git a/e2e/zoneless-env/tsconfig-esm.spec.json b/e2e/zoneless-env/tsconfig-esm.spec.json
new file mode 100644
index 0000000000..2007b41c6e
--- /dev/null
+++ b/e2e/zoneless-env/tsconfig-esm.spec.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig-base.spec.json",
+ "compilerOptions": {
+ "module": "ES2022",
+ "esModuleInterop": true
+ }
+}
diff --git a/setup-env/utils.mjs b/setup-env/utils.js
similarity index 71%
rename from setup-env/utils.mjs
rename to setup-env/utils.js
index eceb631a4e..41b592793a 100644
--- a/setup-env/utils.mjs
+++ b/setup-env/utils.js
@@ -1,13 +1,13 @@
-import { TextDecoder, TextEncoder } from 'util';
+const { TextDecoder, TextEncoder } = require('util');
-export const polyfillEncoder = () => {
+const polyfillEncoder = () => {
if (typeof globalThis.TextEncoder === 'undefined') {
globalThis.TextEncoder = TextEncoder;
globalThis.TextDecoder = TextDecoder;
}
};
-export const resolveTestEnvOptions = (options) => {
+const resolveTestEnvOptions = (options) => {
const globalTestEnvOptions = globalThis.ngJest?.testEnvironmentOptions;
if (globalTestEnvOptions) {
console.warn(
@@ -17,3 +17,8 @@ export const resolveTestEnvOptions = (options) => {
return globalTestEnvOptions ?? options;
};
+
+module.exports = {
+ polyfillEncoder,
+ resolveTestEnvOptions,
+};
diff --git a/setup-env/zone/index.js b/setup-env/zone/index.js
index b2b2d2a17a..31301cbf85 100644
--- a/setup-env/zone/index.js
+++ b/setup-env/zone/index.js
@@ -1,38 +1,20 @@
require('zone.js');
require('zone.js/testing');
-const { TextEncoder, TextDecoder } = require('util');
-
const { getTestBed } = require('@angular/core/testing');
const {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} = require('@angular/platform-browser-dynamic/testing');
-const polyfillEncoder = () => {
- if (typeof globalThis.TextEncoder === 'undefined') {
- globalThis.TextEncoder = TextEncoder;
- globalThis.TextDecoder = TextDecoder;
- }
-};
-
-const resolveTestEnvOptions = (options) => {
- const globalTestEnvOptions = globalThis.ngJest?.testEnvironmentOptions;
- if (globalTestEnvOptions) {
- console.warn(
- 'Setting testEnvironmentOptions via globalThis.ngJest is deprecated. Please provide testEnvironmentOptions via function argument',
- );
- }
-
- return globalTestEnvOptions ?? options;
-};
+const { polyfillEncoder, resolveTestEnvOptions } = require('../utils');
const setupZoneTestEnv = (options) => {
polyfillEncoder();
const testEnvironmentOptions = resolveTestEnvOptions(options);
getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
+ [BrowserDynamicTestingModule],
platformBrowserDynamicTesting(),
testEnvironmentOptions,
);
diff --git a/setup-env/zone/index.mjs b/setup-env/zone/index.mjs
index fe0d2a993c..68fe0afbb0 100644
--- a/setup-env/zone/index.mjs
+++ b/setup-env/zone/index.mjs
@@ -4,15 +4,19 @@ import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
-import { polyfillEncoder, resolveTestEnvOptions } from '../utils.mjs';
+import { polyfillEncoder, resolveTestEnvOptions } from '../utils';
-export const setupZoneTestEnv = (options) => {
+const setupZoneTestEnv = (options) => {
polyfillEncoder();
const testEnvironmentOptions = resolveTestEnvOptions(options);
getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
+ [BrowserDynamicTestingModule],
platformBrowserDynamicTesting(),
testEnvironmentOptions,
);
};
+
+export {
+ setupZoneTestEnv,
+}
diff --git a/setup-env/zoneless/index.js b/setup-env/zoneless/index.js
index b725a157ad..6ef884f540 100644
--- a/setup-env/zoneless/index.js
+++ b/setup-env/zoneless/index.js
@@ -1,8 +1,48 @@
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-const setupZonelessTestEnv = (_options) => {
+const { provideExperimentalZonelessChangeDetection, NgModule, ErrorHandler } = require('@angular/core');
+const { getTestBed } = require('@angular/core/testing');
+const {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting,
+} = require('@angular/platform-browser-dynamic/testing');
+
+const { polyfillEncoder, resolveTestEnvOptions } = require('../utils');
+
+const provideZonelessConfig = () => {
+ class TestModule {}
+ NgModule({
+ providers: [
+ provideExperimentalZonelessChangeDetection(),
+ {
+ provide: ErrorHandler,
+ useValue: {
+ handleError: (e) => {
+ throw e;
+ },
+ },
+ },
+ ],
+ })(TestModule);
+
+ return TestModule;
+};
+
+const setupZonelessTestEnv = (options) => {
+ polyfillEncoder();
+ if (typeof provideExperimentalZonelessChangeDetection !== 'undefined') {
+ const testEnvironmentOptions = resolveTestEnvOptions(options);
+
+ getTestBed().initTestEnvironment(
+ [BrowserDynamicTestingModule, provideZonelessConfig()],
+ platformBrowserDynamicTesting(),
+ testEnvironmentOptions,
+ );
+
+ return;
+ }
+
throw Error(
- 'Zoneless testing environment only works when running Jest in ESM mode with Jest 29. ' +
- 'Jest 30+ will support to work with CommonJS mode.',
+ 'Cannot find provideExperimentalZonelessChangeDetection() to setup zoneless testing environment. ' +
+ 'Please use setupZoneTestEnv() from jest-preset-angular/setup-env/setup-zone-env.mjs instead.',
);
};
diff --git a/setup-env/zoneless/index.mjs b/setup-env/zoneless/index.mjs
index b63cd62e6e..ce66a4cc90 100644
--- a/setup-env/zoneless/index.mjs
+++ b/setup-env/zoneless/index.mjs
@@ -2,29 +2,34 @@ import { ErrorHandler, NgModule, provideExperimentalZonelessChangeDetection } fr
import { getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
-import { polyfillEncoder, resolveTestEnvOptions } from '../utils.mjs';
+import { polyfillEncoder, resolveTestEnvOptions } from '../utils';
-export const setupZonelessTestEnv = (options) => {
- if (typeof provideExperimentalZonelessChangeDetection !== 'undefined') {
- polyfillEncoder();
- const testEnvironmentOptions = resolveTestEnvOptions(options);
- @NgModule({
- providers: [
- provideExperimentalZonelessChangeDetection(),
- {
- provide: ErrorHandler,
- useValue: {
- handleError: (e) => {
- throw e;
- },
+const provideZonelessConfig = () => {
+ class TestModule {}
+ NgModule({
+ providers: [
+ provideExperimentalZonelessChangeDetection(),
+ {
+ provide: ErrorHandler,
+ useValue: {
+ handleError: (e) => {
+ throw e;
},
},
- ],
- })
- export class TestModule {}
+ },
+ ],
+ })(TestModule);
+
+ return TestModule;
+};
+
+const setupZonelessTestEnv = (options) => {
+ polyfillEncoder();
+ if (typeof provideExperimentalZonelessChangeDetection !== 'undefined') {
+ const testEnvironmentOptions = resolveTestEnvOptions(options);
getTestBed().initTestEnvironment(
- [BrowserDynamicTestingModule, TestModule],
+ [BrowserDynamicTestingModule, provideZonelessConfig()],
platformBrowserDynamicTesting(),
testEnvironmentOptions,
);
@@ -34,6 +39,10 @@ export const setupZonelessTestEnv = (options) => {
throw Error(
'Cannot find provideExperimentalZonelessChangeDetection() to setup zoneless testing environment. ' +
- 'Please use setupZoneTestEnv() from jest-preset-angular/setup-env/setup-zone-env.mjs instead.',
+ 'Please use setupZoneTestEnv() from jest-preset-angular/setup-env/setup-zone-env.mjs instead.',
);
};
+
+export {
+ setupZonelessTestEnv
+}
diff --git a/setup-jest.js b/setup-jest.js
index 4528ff46e6..4ac9724c84 100644
--- a/setup-jest.js
+++ b/setup-jest.js
@@ -25,4 +25,8 @@ if (typeof globalThis.TextEncoder === 'undefined') {
const testEnvironmentOptions = globalThis.ngJest?.testEnvironmentOptions ?? Object.create(null);
-getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), testEnvironmentOptions);
+getTestBed().initTestEnvironment(
+ [BrowserDynamicTestingModule],
+ platformBrowserDynamicTesting(),
+ testEnvironmentOptions,
+);
diff --git a/setup-jest.mjs b/setup-jest.mjs
index 19752ef617..e4bd512a42 100644
--- a/setup-jest.mjs
+++ b/setup-jest.mjs
@@ -22,4 +22,4 @@ if (typeof globalThis.TextEncoder === 'undefined') {
const testEnvironmentOptions = globalThis.ngJest?.testEnvironmentOptions ?? Object.create(null);
-getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), testEnvironmentOptions);
+getTestBed().initTestEnvironment([BrowserDynamicTestingModule], platformBrowserDynamicTesting(), testEnvironmentOptions);
diff --git a/src/config/setup-jest.spec.ts b/src/config/setup-jest.spec.ts
index 1de0e5bd21..634f6fbbec 100644
--- a/src/config/setup-jest.spec.ts
+++ b/src/config/setup-jest.spec.ts
@@ -28,6 +28,7 @@ jest.mock('@angular/core/testing', () => {
class BrowserDynamicTestingModuleStub {}
class PlatformRefStub {}
+class ErrorHandlerStub {}
const mockPlatformBrowserDynamicTesting = jest.fn(() => new PlatformRefStub());
jest.mock('@angular/platform-browser-dynamic/testing', () => {
return {
@@ -35,14 +36,31 @@ jest.mock('@angular/platform-browser-dynamic/testing', () => {
platformBrowserDynamicTesting: mockPlatformBrowserDynamicTesting,
};
});
+const mockProvideExperimentalZonelessChangeDetection = jest.fn();
+jest.mock('@angular/core', () => {
+ return {
+ provideExperimentalZonelessChangeDetection: mockProvideExperimentalZonelessChangeDetection,
+ ErrorHandler: ErrorHandlerStub,
+ NgModule: () => {
+ return jest.fn();
+ },
+ };
+});
describe('setup-jest', () => {
const assertOnInitTestEnv = (): void => {
expect(mockGetTestBed).toHaveBeenCalled();
- expect(mockInitTestEnvironment).toHaveBeenCalled();
- expect(mockInitTestEnvironment.mock.calls[0][0]).toBeInstanceOf(BrowserDynamicTestingModuleStub);
+ expect(mockInitTestEnvironment.mock.calls[0][0][0]).toBeInstanceOf(BrowserDynamicTestingModuleStub);
expect(mockPlatformBrowserDynamicTesting).toHaveBeenCalled();
expect(mockPlatformBrowserDynamicTesting.mock.results[0].value).toBeInstanceOf(PlatformRefStub);
+ expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({
+ teardown: {
+ destroyAfterEach: false,
+ rethrowErrors: true,
+ },
+ errorOnUnknownElements: true,
+ errorOnUnknownProperties: true,
+ });
};
beforeEach(() => {
@@ -53,7 +71,7 @@ describe('setup-jest', () => {
});
describe('for CJS setup-jest, test environment initialization', () => {
- test('should call getTestBed() and initTestEnvironment() with the testEnvironmentOptions passed to ngJest', async () => {
+ it('should setup test environment with setup-jest file', async () => {
globalThis.ngJest = {
testEnvironmentOptions: {
teardown: {
@@ -65,28 +83,15 @@ describe('setup-jest', () => {
},
};
- await import('../../setup-jest');
+ await import('../../setup-jest.js');
+ expect(globalThis.TextEncoder).toBeDefined();
expect(mockZoneJs).toHaveBeenCalled();
expect(mockZoneJsTesting).toHaveBeenCalled();
assertOnInitTestEnv();
- expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({
- teardown: {
- destroyAfterEach: false,
- rethrowErrors: true,
- },
- errorOnUnknownElements: true,
- errorOnUnknownProperties: true,
- });
});
- test('should always have TextEncoder in globalThis', async () => {
- await import('../../setup-jest');
-
- expect(globalThis.TextEncoder).toBeDefined();
- });
-
- it('should call getTestBed() and initTestEnvironment() with the testEnvironmentOptions passed as argument with setupZoneTestEnv()', async () => {
+ it('should setup test environment with setupZoneTestEnv()', async () => {
const { setupZoneTestEnv } = await import('../../setup-env/zone/index.js');
setupZoneTestEnv({
@@ -98,10 +103,16 @@ describe('setup-jest', () => {
errorOnUnknownProperties: true,
});
+ expect(globalThis.TextEncoder).toBeDefined();
expect(mockZoneJs).toHaveBeenCalled();
expect(mockZoneJsTesting).toHaveBeenCalled();
assertOnInitTestEnv();
- expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({
+ });
+
+ it('should setup test environment with setupZonelessTestEnv()', async () => {
+ const { setupZonelessTestEnv } = await import('../../setup-env/zoneless/index.js');
+
+ setupZonelessTestEnv({
teardown: {
destroyAfterEach: false,
rethrowErrors: true,
@@ -109,19 +120,17 @@ describe('setup-jest', () => {
errorOnUnknownElements: true,
errorOnUnknownProperties: true,
});
- });
-
- it('should always have TextEncoder in globalThis with setupZoneTestEnv()', async () => {
- const { setupZoneTestEnv } = await import('../../setup-env/zone/index.js');
-
- setupZoneTestEnv();
expect(globalThis.TextEncoder).toBeDefined();
+ expect(mockZoneJs).not.toHaveBeenCalled();
+ expect(mockZoneJsTesting).not.toHaveBeenCalled();
+ assertOnInitTestEnv();
+ expect(mockProvideExperimentalZonelessChangeDetection).toHaveBeenCalled();
});
});
describe('for ESM setup-jest, test environment initialization', () => {
- test('should call getTestBed() and initTestEnvironment() with the testEnvironmentOptions passed to ngJest', async () => {
+ it('should setup test environment with setup-jest file', async () => {
globalThis.ngJest = {
testEnvironmentOptions: {
teardown: {
@@ -135,26 +144,13 @@ describe('setup-jest', () => {
await import('../../setup-jest.mjs');
+ expect(globalThis.TextEncoder).toBeDefined();
expect(mockZoneJs).toHaveBeenCalled();
expect(mockZoneJsTesting).toHaveBeenCalled();
assertOnInitTestEnv();
- expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({
- teardown: {
- destroyAfterEach: false,
- rethrowErrors: true,
- },
- errorOnUnknownElements: true,
- errorOnUnknownProperties: true,
- });
});
- test('should always have TextEncoder in globalThis', async () => {
- await import('../../setup-jest.mjs');
-
- expect(globalThis.TextEncoder).toBeDefined();
- });
-
- it('should call getTestBed() and initTestEnvironment() with the testEnvironmentOptions passed as argument with setupZoneTestEnv()', async () => {
+ it('should setup test environment with setupZoneTestEnv()', async () => {
const { setupZoneTestEnv } = await import('../../setup-env/zone/index.mjs');
setupZoneTestEnv({
@@ -166,10 +162,16 @@ describe('setup-jest', () => {
errorOnUnknownProperties: true,
});
+ expect(globalThis.TextEncoder).toBeDefined();
expect(mockZoneJs).toHaveBeenCalled();
expect(mockZoneJsTesting).toHaveBeenCalled();
assertOnInitTestEnv();
- expect(mockInitTestEnvironment.mock.calls[0][2]).toEqual({
+ });
+
+ it('should setup test environment with setupZonelessTestEnv()', async () => {
+ const { setupZonelessTestEnv } = await import('../../setup-env/zoneless/index.mjs');
+
+ setupZonelessTestEnv({
teardown: {
destroyAfterEach: false,
rethrowErrors: true,
@@ -177,14 +179,12 @@ describe('setup-jest', () => {
errorOnUnknownElements: true,
errorOnUnknownProperties: true,
});
- });
-
- it('should always have TextEncoder in globalThis with setupZoneTestEnv()', async () => {
- const { setupZoneTestEnv } = await import('../../setup-env/zone/index.mjs');
-
- setupZoneTestEnv();
expect(globalThis.TextEncoder).toBeDefined();
+ expect(mockZoneJs).not.toHaveBeenCalled();
+ expect(mockZoneJsTesting).not.toHaveBeenCalled();
+ assertOnInitTestEnv();
+ expect(mockProvideExperimentalZonelessChangeDetection).toHaveBeenCalled();
});
});
});
diff --git a/website/docs/getting-started/test-environment.md b/website/docs/getting-started/test-environment.md
index a1bd45a73f..f7a666ec97 100644
--- a/website/docs/getting-started/test-environment.md
+++ b/website/docs/getting-started/test-environment.md
@@ -82,12 +82,6 @@ export default jestConfig;
Configures a test environment that **DOESN'T** use `zone.js`, as described in [Angular experimental zoneless guide](https://angular.dev/guide/experimental/zoneless).
It is designed for projects that have disabled `zone.js`, which can lead to improved performance and simplified testing.
-:::important
-
-This function is only supported in Jest `ESM` mode in [Jest 29](https://github.com/jestjs/jest/issues/10962). Jest 30+ will support to use for `CommonJS` mode.
-
-:::
-
You can customize the environment by providing options as function arguments.
#### Parameters
@@ -98,6 +92,15 @@ You can customize the environment by providing options as function arguments.
- Create a Jest setup file:
+```ts tab={"label": "TypeScript CJS"}
+// setup-jest.ts
+import { setupZonelessTestEnv } from 'jest-preset-angular/setup-env/zoneless';
+
+setupZonelessTestEnv({
+ //...options
+});
+```
+
```ts tab={"label": "TypeScript ESM"}
// setup-jest.ts
import { setupZonelessTestEnv } from 'jest-preset-angular/setup-env/zoneless/index.mjs';
@@ -109,6 +112,18 @@ setupZonelessTestEnv({
- Update your Jest configuration:
+```ts tab={"label": "TypeScript CJS"}
+// jest.config.mts
+import type { Config } from 'jest';
+
+const jestConfig: Config = {
+ preset: 'jest-preset-angular',
+ setupFilesAfterEnv: ['/setup-jest.ts'],
+};
+
+export default jestConfig;
+```
+
```ts tab={"label": "TypeScript ESM"}
// jest.config.mts
import type { Config } from 'jest';
diff --git a/website/versioned_docs/version-14.3/getting-started/test-environment.md b/website/versioned_docs/version-14.3/getting-started/test-environment.md
index a1bd45a73f..f7a666ec97 100644
--- a/website/versioned_docs/version-14.3/getting-started/test-environment.md
+++ b/website/versioned_docs/version-14.3/getting-started/test-environment.md
@@ -82,12 +82,6 @@ export default jestConfig;
Configures a test environment that **DOESN'T** use `zone.js`, as described in [Angular experimental zoneless guide](https://angular.dev/guide/experimental/zoneless).
It is designed for projects that have disabled `zone.js`, which can lead to improved performance and simplified testing.
-:::important
-
-This function is only supported in Jest `ESM` mode in [Jest 29](https://github.com/jestjs/jest/issues/10962). Jest 30+ will support to use for `CommonJS` mode.
-
-:::
-
You can customize the environment by providing options as function arguments.
#### Parameters
@@ -98,6 +92,15 @@ You can customize the environment by providing options as function arguments.
- Create a Jest setup file:
+```ts tab={"label": "TypeScript CJS"}
+// setup-jest.ts
+import { setupZonelessTestEnv } from 'jest-preset-angular/setup-env/zoneless';
+
+setupZonelessTestEnv({
+ //...options
+});
+```
+
```ts tab={"label": "TypeScript ESM"}
// setup-jest.ts
import { setupZonelessTestEnv } from 'jest-preset-angular/setup-env/zoneless/index.mjs';
@@ -109,6 +112,18 @@ setupZonelessTestEnv({
- Update your Jest configuration:
+```ts tab={"label": "TypeScript CJS"}
+// jest.config.mts
+import type { Config } from 'jest';
+
+const jestConfig: Config = {
+ preset: 'jest-preset-angular',
+ setupFilesAfterEnv: ['/setup-jest.ts'],
+};
+
+export default jestConfig;
+```
+
```ts tab={"label": "TypeScript ESM"}
// jest.config.mts
import type { Config } from 'jest';