diff --git a/examples/example-app-monorepo/apps/app1/jest-esm.config.mjs b/examples/example-app-monorepo/apps/app1/jest-esm.config.mjs index 85b9d51de2..ee72dffb61 100644 --- a/examples/example-app-monorepo/apps/app1/jest-esm.config.mjs +++ b/examples/example-app-monorepo/apps/app1/jest-esm.config.mjs @@ -1,11 +1,12 @@ +import ngPreset from 'jest-preset-angular/presets/index.js'; + /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ const jestConfig = { + ...ngPreset.defaultsESM, displayName: 'app1', - preset: 'jest-preset-angular/presets/defaults-esm', globals: { 'ts-jest': { - useESM: true, - stringifyContentPathRegex: '\\.(html|svg)$', + ...ngPreset.defaultsESM.globals["ts-jest"], tsconfig: '/tsconfig-esm.spec.json', }, }, @@ -13,7 +14,7 @@ const jestConfig = { tslib: 'tslib/tslib.es6.js', rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js', }, - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-monorepo/apps/app1/setup-jest-esm.ts b/examples/example-app-monorepo/apps/app1/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-monorepo/apps/app1/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-monorepo/apps/app1/setup-jest.ts b/examples/example-app-monorepo/apps/app1/setup-jest.ts index f9f40bc926..9a3535cfee 100644 --- a/examples/example-app-monorepo/apps/app1/setup-jest.ts +++ b/examples/example-app-monorepo/apps/app1/setup-jest.ts @@ -1,10 +1,2 @@ -// Can't use standard setup-jest, b/c it uses require() -// import 'jest-preset-angular/setup-jest'; - -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; +import 'jest-preset-angular/setup-jest'; import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/examples/example-app-monorepo/libs/user/jest-esm.config.mjs b/examples/example-app-monorepo/libs/user/jest-esm.config.mjs index 0ee6af917c..1256e3eb4b 100644 --- a/examples/example-app-monorepo/libs/user/jest-esm.config.mjs +++ b/examples/example-app-monorepo/libs/user/jest-esm.config.mjs @@ -1,11 +1,12 @@ +import ngPreset from 'jest-preset-angular/presets/index.js'; + /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ const jestConfig = { + ...ngPreset.defaultsESM, displayName: 'user-lib', - preset: 'jest-preset-angular/presets/defaults-esm', globals: { 'ts-jest': { - useESM: true, - stringifyContentPathRegex: '\\.(html|svg)$', + ...ngPreset.defaultsESM.globals["ts-jest"], tsconfig: '/tsconfig-esm.spec.json', }, }, @@ -13,7 +14,7 @@ const jestConfig = { tslib: 'tslib/tslib.es6.js', rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js', }, - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-monorepo/libs/user/setup-jest-esm.ts b/examples/example-app-monorepo/libs/user/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-monorepo/libs/user/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-monorepo/libs/user/setup-jest.ts b/examples/example-app-monorepo/libs/user/setup-jest.ts index f9f40bc926..9a3535cfee 100644 --- a/examples/example-app-monorepo/libs/user/setup-jest.ts +++ b/examples/example-app-monorepo/libs/user/setup-jest.ts @@ -1,10 +1,2 @@ -// Can't use standard setup-jest, b/c it uses require() -// import 'jest-preset-angular/setup-jest'; - -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; +import 'jest-preset-angular/setup-jest'; import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/examples/example-app-v11/jest-esm.config.mjs b/examples/example-app-v11/jest-esm.config.mjs index b4aec6e52e..e5fbc86bda 100644 --- a/examples/example-app-v11/jest-esm.config.mjs +++ b/examples/example-app-v11/jest-esm.config.mjs @@ -15,7 +15,7 @@ const jestConfig = { }, }, globalSetup: 'jest-preset-angular/global-setup', - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-v11/setup-jest-esm.ts b/examples/example-app-v11/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-v11/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-v12/jest-esm.config.mjs b/examples/example-app-v12/jest-esm.config.mjs index b4aec6e52e..e5fbc86bda 100644 --- a/examples/example-app-v12/jest-esm.config.mjs +++ b/examples/example-app-v12/jest-esm.config.mjs @@ -15,7 +15,7 @@ const jestConfig = { }, }, globalSetup: 'jest-preset-angular/global-setup', - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-v12/setup-jest-esm.ts b/examples/example-app-v12/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-v12/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-v13/jest-esm.config.mjs b/examples/example-app-v13/jest-esm.config.mjs index 30ef9b63ee..9c654c3611 100644 --- a/examples/example-app-v13/jest-esm.config.mjs +++ b/examples/example-app-v13/jest-esm.config.mjs @@ -19,7 +19,7 @@ const jestConfig = { tslib: 'tslib/tslib.es6.js', rxjs: '/node_modules/rxjs/dist/bundles/rxjs.umd.js', }, - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-v13/setup-jest-esm.ts b/examples/example-app-v13/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-v13/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-v13/setup-jest.ts b/examples/example-app-v13/setup-jest.ts index f9f40bc926..9a3535cfee 100644 --- a/examples/example-app-v13/setup-jest.ts +++ b/examples/example-app-v13/setup-jest.ts @@ -1,10 +1,2 @@ -// Can't use standard setup-jest, b/c it uses require() -// import 'jest-preset-angular/setup-jest'; - -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; +import 'jest-preset-angular/setup-jest'; import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/examples/example-app-yarn-workspace/packages/angular-app/jest-esm.config.mjs b/examples/example-app-yarn-workspace/packages/angular-app/jest-esm.config.mjs index d7554e955b..98442e606a 100644 --- a/examples/example-app-yarn-workspace/packages/angular-app/jest-esm.config.mjs +++ b/examples/example-app-yarn-workspace/packages/angular-app/jest-esm.config.mjs @@ -19,7 +19,7 @@ const jestConfig = { tslib: 'tslib/tslib.es6.js', rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js', }, - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-yarn-workspace/packages/angular-app/setup-jest-esm.ts b/examples/example-app-yarn-workspace/packages/angular-app/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-yarn-workspace/packages/angular-app/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-yarn-workspace/packages/angular-app/setup-jest.ts b/examples/example-app-yarn-workspace/packages/angular-app/setup-jest.ts index f9f40bc926..9a3535cfee 100644 --- a/examples/example-app-yarn-workspace/packages/angular-app/setup-jest.ts +++ b/examples/example-app-yarn-workspace/packages/angular-app/setup-jest.ts @@ -1,10 +1,2 @@ -// Can't use standard setup-jest, b/c it uses require() -// import 'jest-preset-angular/setup-jest'; - -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; +import 'jest-preset-angular/setup-jest'; import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/examples/example-app-yarn-workspace/packages/user/jest-esm.config.mjs b/examples/example-app-yarn-workspace/packages/user/jest-esm.config.mjs index d7554e955b..98442e606a 100644 --- a/examples/example-app-yarn-workspace/packages/user/jest-esm.config.mjs +++ b/examples/example-app-yarn-workspace/packages/user/jest-esm.config.mjs @@ -19,7 +19,7 @@ const jestConfig = { tslib: 'tslib/tslib.es6.js', rxjs: '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js', }, - setupFilesAfterEnv: ['/setup-jest.ts'], + setupFilesAfterEnv: ['/setup-jest-esm.ts'], } export default jestConfig; diff --git a/examples/example-app-yarn-workspace/packages/user/setup-jest-esm.ts b/examples/example-app-yarn-workspace/packages/user/setup-jest-esm.ts new file mode 100644 index 0000000000..f35c45e008 --- /dev/null +++ b/examples/example-app-yarn-workspace/packages/user/setup-jest-esm.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular/setup-jest.mjs'; +import './jest-global-mocks'; diff --git a/examples/example-app-yarn-workspace/packages/user/setup-jest.ts b/examples/example-app-yarn-workspace/packages/user/setup-jest.ts index f9f40bc926..9a3535cfee 100644 --- a/examples/example-app-yarn-workspace/packages/user/setup-jest.ts +++ b/examples/example-app-yarn-workspace/packages/user/setup-jest.ts @@ -1,10 +1,2 @@ -// Can't use standard setup-jest, b/c it uses require() -// import 'jest-preset-angular/setup-jest'; - -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; +import 'jest-preset-angular/setup-jest'; import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/scripts/test-examples.js b/scripts/test-examples.js index 03825d15e8..41b39a406f 100755 --- a/scripts/test-examples.js +++ b/scripts/test-examples.js @@ -35,11 +35,13 @@ const executeTest = (projectPath) => { logger.log('installing bundled version of jest-preset-angular'); logger.log(); - ['build', 'presets', 'global-setup.js', 'jest-preset.js', 'package.json', 'setup-jest.js'].forEach((asset) => { - const assetToReplace = join(projectPath, 'node_modules', 'jest-preset-angular', asset); - const assetToCopy = join(rootDir, asset); - copySync(assetToCopy, assetToReplace, {}); - }); + ['build', 'presets', 'global-setup.js', 'jest-preset.js', 'package.json', 'setup-jest.js', 'setup-jest.mjs'].forEach( + (asset) => { + const assetToReplace = join(projectPath, 'node_modules', 'jest-preset-angular', asset); + const assetToCopy = join(rootDir, asset); + copySync(assetToCopy, assetToReplace, {}); + } + ); // then we can run the tests const cmdLine = ['yarn', 'test']; diff --git a/setup-jest.js b/setup-jest.js index 1c1c81242b..f982ec61bc 100644 --- a/setup-jest.js +++ b/setup-jest.js @@ -1 +1,9 @@ -module.exports = require('./build/config/setup-jest'); +require('zone.js/bundles/zone-testing-bundle.umd'); + +const { getTestBed } = require('@angular/core/testing'); +const { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} = require('@angular/platform-browser-dynamic/testing'); + +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); diff --git a/src/config/setup-jest.ts b/setup-jest.mjs similarity index 83% rename from src/config/setup-jest.ts rename to setup-jest.mjs index e07b9714ba..480364fd0d 100644 --- a/src/config/setup-jest.ts +++ b/setup-jest.mjs @@ -1,5 +1,4 @@ -import 'zone.js'; -import 'zone.js/testing'; +import 'zone.js/fesm2015/zone-testing-bundle.min.js'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; diff --git a/src/config/setup-jest.spec.ts b/src/config/setup-jest.spec.ts index 3439b6e5b2..2388945a33 100644 --- a/src/config/setup-jest.spec.ts +++ b/src/config/setup-jest.spec.ts @@ -1,20 +1,20 @@ const mockInitTestEnvironment = jest.fn(); -const mockZoneJs = jest.fn(); -const mockZoneJsTesting = jest.fn(); +const mockUmdZoneJs = jest.fn(); +const mockEsmZoneJs = jest.fn(); const mockGetTestBed = jest.fn(() => { return { initTestEnvironment: mockInitTestEnvironment, }; }); -jest.mock('zone.js', () => { - const mockedResult = mockZoneJs(); +jest.mock('zone.js/bundles/zone-testing-bundle.umd', () => { + const mockedResult = mockUmdZoneJs(); return { mockedResult, }; }); -jest.mock('zone.js/testing', () => { - const mockedResult = mockZoneJsTesting(); +jest.mock('zone.js/fesm2015/zone-testing-bundle.min.js', () => { + const mockedResult = mockEsmZoneJs(); return { mockedResult, @@ -36,14 +36,30 @@ jest.mock('@angular/platform-browser-dynamic/testing', () => { }; }); -test('should initialize test environment with getTestBed() and initTestEnvironment()', async () => { - await import('../config/setup-jest'); +describe('setup-jest', () => { + const assertOnInitTestEnv = (): void => { + expect(mockGetTestBed).toHaveBeenCalled(); + expect(mockInitTestEnvironment).toHaveBeenCalled(); + expect(mockInitTestEnvironment.mock.calls[0][0]).toBeInstanceOf(BrowserDynamicTestingModuleStub); + expect(mockPlatformBrowserDynamicTesting).toHaveBeenCalled(); + expect(mockPlatformBrowserDynamicTesting.mock.results[0].value).toBeInstanceOf(PlatformRefStub); + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('should initialize test environment with getTestBed() and initTestEnvironment() for CJS setup-jest', async () => { + await import('../../setup-jest'); + + expect(mockUmdZoneJs).toHaveBeenCalled(); + assertOnInitTestEnv(); + }); + + test('should initialize test environment with getTestBed() and initTestEnvironment() for ESM setup-jest', async () => { + await import('../../setup-jest.mjs'); - expect(mockZoneJs).toHaveBeenCalled(); - expect(mockZoneJsTesting).toHaveBeenCalled(); - expect(mockGetTestBed).toHaveBeenCalled(); - expect(mockInitTestEnvironment).toHaveBeenCalled(); - expect(mockInitTestEnvironment.mock.calls[0][0]).toBeInstanceOf(BrowserDynamicTestingModuleStub); - expect(mockPlatformBrowserDynamicTesting).toHaveBeenCalled(); - expect(mockPlatformBrowserDynamicTesting.mock.results[0].value).toBeInstanceOf(PlatformRefStub); + expect(mockEsmZoneJs).toHaveBeenCalled(); + assertOnInitTestEnv(); + }); }); diff --git a/tsconfig.json b/tsconfig.json index f8079bd39f..e2c0693de6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "baseUrl": "./", "strict": true, + "allowJs": true, "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, diff --git a/website/docs/guides/angular-13+.md b/website/docs/guides/angular-13+.md index 2a9532d2ae..dcbda4f11e 100644 --- a/website/docs/guides/angular-13+.md +++ b/website/docs/guides/angular-13+.md @@ -5,7 +5,6 @@ title: Angular >=13 **Angular 13** introduces ESM package format for Angular packages. `jest-preset-angular` currently supports testing with Jest in `CommonJS` mode with **Angular 13** using [default preset](../getting-started/presets.md). -Jest ESM support with **Angular 13** is new and may have issues. :::important @@ -70,25 +69,13 @@ Before upgrading to ng13 and switching to ES Modules, your `setup-jest.ts` file ```ts // setup-jest.ts import 'jest-preset-angular/setup-jest'; -import './jest-global-mocks'; ``` -The `jest-preset-angular/setup-jest` file doesn't work with ESM, because it uses `require`. For now you should skip using this file, and replace the contents of your `setup-jest.ts` with: +or for ESM mode ```ts // setup-jest.ts -import 'zone.js/fesm2015/zone-testing-bundle.min.js'; -import './jest-global-mocks'; - -import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; - -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { - destroyAfterEach: true, // Angular recommends this, but it may break existing tests - }, -}); -getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); +import 'jest-preset-angular/setup-jest.mjs'; ``` ## Potential issues with Angular 13 ESM package format and workaround diff --git a/website/docs/guides/esm-support.md b/website/docs/guides/esm-support.md index c2d3870269..db0aacb55e 100644 --- a/website/docs/guides/esm-support.md +++ b/website/docs/guides/esm-support.md @@ -15,6 +15,12 @@ We have [example apps](https://github.com/thymikee/jest-preset-angular/tree/main ::: +Besides, there is `setup-jest.mjs` to add to Jest setup file to ensure that Jest can set up test environment properly. + +```ts +import 'jest-preset-angular/setup-jest.mjs'; +``` + ### Examples #### Manual configuration