bug(transloco): error when running tests after updating to v5.0.9
dzhavat opened this issue Β· comments
Is there an existing issue for this?
- I have searched the existing issues
Which Transloco package(s) are the source of the bug?
Transloco
Is this a regression?
No
Current behavior
After updating Transloco to version 5.0.9
, I'm getting the following error in my tests:
Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
β’ If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
β’ If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
β’ To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
β’ If you need a custom transformation specify a "transform" option in your config.
β’ If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
C:/Projects/greenforce-frontend/node_modules/@ngneat/transloco/node_modules/flat/index.d.ts:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export interface FlattenOptions {
^^^^^^
SyntaxError: Unexpected token 'export'
17 | import { HttpClientTestingModule } from '@angular/common/http/testing';
18 | import { TestBed } from '@angular/core/testing';
> 19 | import { TRANSLOCO_CONFIG, TRANSLOCO_LOADER } from '@ngneat/transloco';
| ^
20 |
21 | import { translocoProviders } from './dh-transloco.providers';
22 |
at Runtime.createScriptFromCode (../../../../node_modules/jest-runtime/build/index.js:1495:14)
at Object.<anonymous> (../../../../node_modules/@ngneat/transloco/fesm2022/ngneat-transloco.mjs:4:64)
The transloco/fesm2022/ngneat-transloco.mjs:4:64
points to
Expected behavior
Tests can start without issues.
Please provide a link to a minimal reproduction of the bug, if you won't provide a link the issue won't be handled.
Don't have :(
Transloco Config
export const dhTranslocoConfig = translocoConfig({
availableLangs: [DisplayLanguage.Danish, DisplayLanguage.English],
defaultLang: DisplayLanguage.Danish,
fallbackLang: [DisplayLanguage.Danish, DisplayLanguage.English],
flatten: {
aot: environment.production,
},
missingHandler: {
useFallbackTranslation: true,
},
// Remove this option if your application doesn't support changing language in runtime.
reRenderOnLangChange: true,
prodMode: environment.production,
});
Please provide the environment you discovered this bug in
Transloco: 5.0.9
Angular: 16.2.0
Node: 18.12.0
Package Manager: Yarn 3.5.0
OS: Windows
Browser
No response
Additional context
No response
I would like to make a pull request for this bug
No
@dzhavat My guess is that it's related to the flat upgrade, it's now ESM.
Try to enable jest's ESM support and see if that resolves your issue.
Hey @shaharkazaz
Thanks for the quick response. Will check Jest's ESM support to see if that helps.
Hi,
I run into this exact same issue.
- The bug appear exactly in 5.0.8 :
- 5.0.7 => unit tests run OK
- 5.0.8 => unit tests run KO
- I didn't figure out how to enable Jest's ESM. I use Nx and it handle this kind of configuration for me. Here is the relevant configuration :
jest.config.ts
export default {
preset: '../../../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
globals: {},
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
isolatedModules: true,
},
],
},
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
],
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!**/*.stories.ts',
'!**/index.ts',
],
};
jest.preset.js
const nxPreset = require('@nx/jest/preset').default;
module.exports = {
...nxPreset
};
I hope it could help.
My guess is that it's related to the flat upgrade, it's now ESM.
Try to enable jest's ESM support and see if that resolves your issue.
If this is the case it should be an major release, because this would be a breakting change as much as a change can be breaking.
I'm also facing this issue. If you're in an nx workspace you're probably using jest-preset-angular for the jest configuration. They point out how to adjust the configuration to make jest work with esm modules. You can find the documentation here: https://thymikee.github.io/jest-preset-angular/docs/guides/esm-support
In theory this should work, but I'm still struggling with it.
Thanks for the fast reaction and clarification :)
@shaharkazaz The upgrade of the related package you speak, is now only in version 6.0.0, correct? Because this issue also occurs in version ^5.0.7, on a completely fresh nx workspace ( EDIT: Never mind, that package was transparently upgraded to the deprecated 5.0.9 version.npx create-nx-workspace@latest
).
In case anyone else has this issue, I think flatten: {aot: true}
in the transloco module testing factory, is a workaround.
I do have the same issue with the current version "6.0.0". Downgrading to 5.0.7 fixed the issue without any further changes.
I had the same issue in my tests but finally succeeded in solving the issue. Here is how I did workaround it:
- create a "mocks" folder in the root of my Nx workspace.
- create a "flat" folder in the "mocks" folder.
- create an empty index.ts file in the "mocks/flat" folder.
- updated my project's jest.config.ts file an entry to the
moduleNameMapper
property:
flat: '<rootDir>/../../../mocks/flat/index.ts'
(of course, the number of ".." depends on the depth of your jest.config.ts file)
I hope this solution will help people which have the same issue.
Thanks @FabienDehopre for your tip but for us not work.
There is a plan to fix this issue?
the flat
package is now distributed in the ECMAScript module syntax. You'll need to transform code inside the flat
package into plain JavaScript. You can do this by including it in the Jest code transformation. e.g. your jest.config.ts
should look like this:
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
},
],
},
// Ignore node_modules except for .mjs files and the @ngneat package.
transformIgnorePatterns: ['node_modules/?!(.*\\.mjs$|@ngneat)'],
Thanks @Piiiiiiiiiiiim for your solution but, in our case, it makes the tests horribly slow (more than 90 secs and still no test ran). So, I'll stick to my solution for now
NX uses flat
version 5.0.2, @ngneat/transloco
uses version 6.0. Forcing nx
to use flat
version 6.x is not a success, but the other way around works, force transloco to use version 5.0.2, you can do this by adding in package.json
:
"overrides": {
"@ngneat/transloco": {
"flat": "5.0.2"
}
}
Before:
npm ls flat
web-gz-angular-apps@1.3.0 /Users/elmarbeckmann/Code/alliander/web-gz-angular-apps
βββ¬ @ngneat/transloco@6.0.0
β βββ flat@6.0.0
βββ¬ nx@16.10.0
βββ flat@5.0.2
after:
npm ls flat
web-gz-angular-apps@1.3.0 /Users/elmarbeckmann/Code/alliander/web-gz-angular-apps
βββ¬ @ngneat/transloco@6.0.0 overridden
β βββ flat@5.0.2 overridden
βββ¬ nx@16.10.0
βββ flat@5.0.2
Using jest in ESM mode is experimental, and had too many other side effects for my project. I tried overriding flat in package.json, as suggested by @elmarbeckmann, but somehow it didn't work. So I did a mix with the mock solution from @FabienDehopre.
Installed flat 5.02 under an alias, just for jest: npm i flat-cjs-for-jest@npm:flat@5.0.2
Then I configured jest to use that flat package. In jest.config.js
:
moduleNameMapper: {
flat: '<rootDir>/node_modules/flat-cjs-for-jest/index.js',
},
Using jest in ESM mode is experimental, and had too many other side effects for my project. I tried overriding flat in package.json, as suggested by @elmarbeckmann, but somehow it didn't work. So I did a mix with the mock solution from @FabienDehopre.
Installed flat 5.02 under an alias, just for jest:
npm i flat-cjs-for-jest@npm:flat@5.0.2
Then I configured jest to use that flat package. Injest.config.js
:moduleNameMapper: { flat: '<rootDir>/node_modules/flat-cjs-for-jest/index.js', },
wow I didn't even know you could use aliases. awesome.
@elmarbeckmann Would you like to add this important information to the docs? π
@shaharkazaz uhm can I do that? How? You mean by forking the docs and adding it?
@elmarbeckmann I mean opening a PR to Transloco and add the workaround to the unit tests section/FAQ
@elmarbeckmann I mean opening a PR to Transloco and add the workaround to the unit tests section/FAQ
sure, will do!
Easier solution:
#714 (comment)
For me the only working solutions was the one mentioned by @elmarbeckmann
Just leaving this here in case it helps anyone:
For me, a better fix was not to use moduleNameMapper
since that's just a workaround which relies on adding an additional dependency to the older non-ESM version of flat
.
Instead, we can use the transformIgnorePatterns
option to make sure that Jest will convert the ESM flat
package to CommonJS. This way we don't need any additional dependencies.
In my case, this is what it looks like:
// we need to let Jest know which files are ESM so they can be transformed to CommonJS
const esModules = [
'.*\\.mjs$', // .mjs files are always ESM so they need to be transformed always
'flat/', // npm package "flat" is ESM-only from version 6
].join('|');
...
// in jest config:
transformIgnorePatterns: [`node_modules/(?!\\.pnpm|${esModules})`],
NOTE 1: we are using pnpm in our repo. If you don't use pnpm then you can remove \\.pnpm|
from the pattern.
NOTE 2: even better (ideal) scenario would be to go full 100% ESM. Then we would not have to transform esm modules to commonjs anymore. However, achieving this on a large existing repo is not trivial. If you are interested to try it, I recommend reading this article: https://angularexperts.io/blog/total-guide-to-jest-esm-and-angular
Using the transformIgnorePatterns
property:
transformIgnorePatterns: ['node_modules/(?!(date-fns/|flat|lodash-es/|mime|.*\\.mjs$))'],
didn't work for me either, I still got the SyntaxError: Unexpected token 'export'
error
(I don't know why π€)
I managed to get it work with:
moduleNameMapper: { '^flat$': '<rootDir>/node_modules/flat/index.js' },
solution similar to the one of @elmarbeckmann, but with the use of ^
and $
to mitigate this risk of matching unexpected files.
It does not add an additional dependency to an older non-ESM version of flat.
Going 100% ESM and the article of @kfrederix look promising π‘, I'll dig into it soon
Thanks @Piiiiiiiiiiiim for your solution but, in our case, it makes the tests horribly slow (more than 90 secs and still no test ran). So, I'll stick to my solution for now
It seems as the "slowness comes from the regex with the negative lookahead.
For me the issue with flax 6.0.0 was fixed by using:
transformIgnorePatterns: ['node_modules/(?!.*\.mjs$)(?!flat)'],