From 0ab958d9cede938c9a88a7f2dd4ceea17f20174e Mon Sep 17 00:00:00 2001 From: Ahn <27772165+ahnpnl@users.noreply.github.com> Date: Tue, 9 Nov 2021 10:42:07 +0100 Subject: [PATCH] docs(devs-infra): update docs for possible issues in Angular 13 (#1153) --- website/docs/guides/angular-13+.md | 37 ++++++++++--- website/docs/guides/troubleshooting.md | 72 ++++++-------------------- 2 files changed, 45 insertions(+), 64 deletions(-) diff --git a/website/docs/guides/angular-13+.md b/website/docs/guides/angular-13+.md index 0ae5027bf1..d0b87abbaf 100644 --- a/website/docs/guides/angular-13+.md +++ b/website/docs/guides/angular-13+.md @@ -30,7 +30,7 @@ module.exports = { there are no migration steps required -- If one is not having `preset: 'jest-preset-angular'` in Jest config, the config needs to be updated with new values for +- If one is **NOT** having `preset: 'jest-preset-angular'` in Jest config, the config needs to be updated with new values for `resolver`, `transformIgnorePatterns` and `transform`: ```js @@ -45,14 +45,37 @@ module.exports = { }; ``` -:::important -Angular 13 libraries are also built automatically into ESM package format. Therefore, the Angular libraries should also -be added to `transformIgnorePatterns` to avoid Jest error `SyntaxError: Cannot use import statement outside a module`, +## Potential issues with Angular 13 ESM package format and workaround -Example config: +### Cannot import locale data from `@angular/common/locales` or any deep import paths + +- Angular 13 ESM package format makes Jest resolution not able to resolve the correct locale files. Even though we introduced + `ng-jest-resolver` as a part of the preset, this resolver won't work for all scenarios. One might get Jest error like + +``` +Cannot find module '@angular/common/locales/xx' from 'src/app/app.component.spec.ts' +``` + +To fix this issue, one needs to define +`moduleNameMapper` to instruct Jest where to find the files, e.g. ```js -transformIgnorePatterns: ['node_modules/(?!@angular|my-ng-library-a|my-ng-library-b)']; +// jest.config.js +module.exports = { + // ...other options + moduleNameMapper: { + '@angular/common/locales/(.*)$': '/node_modules/@angular/common/locales/$1.mjs', + }, +}; ``` -::: +- Another alternative solution is extending the default [resolver](https://github.com/thymikee/jest-preset-angular/blob/main/src/resolvers/ng-jest-resolver.ts) + of this preset to instruct Jest where to find the files. + +### Usage with Angular libraries which are built with Angular CLI 13 + +Besides, the changes in Angular packages themselves, **Angular** libraries which are built with **Angular CLI 13** also introduce +ESM package format. Similar to Angular packages, Jest doesn't understand `.mjs` files which are in these new format +libraries in Jest **CommonJS** mode. + +To fix this issue, one should follow our [troubleshooting instruction](troubleshooting.md#unexpected-token-importexportother) diff --git a/website/docs/guides/troubleshooting.md b/website/docs/guides/troubleshooting.md index d55460e264..82b7240923 100644 --- a/website/docs/guides/troubleshooting.md +++ b/website/docs/guides/troubleshooting.md @@ -65,71 +65,29 @@ Reference: https://github.com/angular/material2/issues/7101 ### Unexpected token [import|export|other] -This means, that a file is not transformed through TypeScript compiler, e.g. because it is a JS file with TS syntax, or it is published to npm as uncompiled source files. Here's what you can do. - -#### Adjust your `tsconfig.spec.json`: - -Since Angular released v6, the default `tsconfig.json` and `tsconfig.spec.json` have been changed. Therefore, `jest` will throw an error - -``` - ({"Object.":function(module,exports,require,__dirname,__filename,global,jest){import 'jest-preset-angular/setup-jest'; - ^^^^^^ - SyntaxError: Unexpected token import - at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17) -``` - -What you need to do is adjust your `tsconfig.spec.json` to add the option `"module": "commonjs",` - -A default `tsconfig.spec.json` after modifying will look like this +This means, that a file is not transformed through `TypeScript` compiler, e.g. because it is a `JS` file with `TS` syntax, or +it is published to npm as uncompiled source files. Here's what you can do. A typical Jest error is like this: ``` -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/spec", - "module": "commonjs", - "types": [ - "jest", - "jsdom", - "node" - ] - }, - "include": [ - "**/*.d.ts" - ] +({"Object.":function(module,exports,require,__dirname,__filename,jest){import * as i0 from '@angular/core'; + ^^^^^^ + SyntaxError: Cannot use import statement outside a module ``` -#### Adjust your `transformIgnorePatterns` whitelist: - -```json5 -{ - jest: { - transformIgnorePatterns: ['node_modules/(?!@ngrx|angular2-ui-switch|ng-dynamic)'], - }, -} -``` - -By default, Jest doesn't transform `node_modules`, because they should be valid JavaScript files. However, it happens that library authors assume that you'll compile their sources. So you have to tell this to Jest explicitly. Above snippet means that `@ngrx`, `angular2-ui-switch` and `ng-dynamic` will be transformed, even though they're `node_modules`. - -### Observable ... is not a function - -Note: This fix is only relevant to Angular v5 and lower. - -Since v1.0 this preset doesn't import whole `rxjs` library by default for variety of reasons. This may result in breaking your tests that relied on this behavior. It may however become cumbersome to include e.g. `rxjs/add/operator/map` or `rxjs/add/operator/do` for every test, so as a workaround you can include common operators or other necessary imports in your `setup-jest.ts` file: +To fix the issue, one needs to adjust `transformIgnorePatterns` whitelist: ```js -import 'jest-preset-angular/setup-jest'; - -// common rxjs imports -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/switchMap'; -import 'rxjs/add/operator/do'; -import 'rxjs/add/operator/catch'; -// ... - -import './jestGlobalMocks'; +// jest.config.js +module.exports = { + // ...other options + transformIgnorePatterns: ['node_modules/(?!@angular|@ngrx)'], +}; ``` +By default, Jest doesn't transform `node_modules`, because they should be valid JavaScript files. However, it happens that +library authors assume that you'll compile their sources. So you have to tell this to Jest explicitly. +Above snippet means that `@angular`, `@ngrx` will be transformed, even though they're `node_modules`. + ### Allow vendor libraries like jQuery, etc... The same like normal Jest configuration, you can load jQuery in your Jest setup file. For example your Jest setup file is `setup-jest.ts` you can declare jQuery: