jsverse / transloco

πŸš€ 😍 The internationalization (i18n) library for Angular

Home Page:https://jsverse.github.io/transloco/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

image

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.

  1. The bug appear exactly in 5.0.8 :
    • 5.0.7 => unit tests run OK
    • 5.0.8 => unit tests run KO
  2. 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.

I've released this as a major version and deprecated v5.0.8-10
Don't reopen this issue as it should be handled by your jest config.

@jontze @dzhavat When you make the upgrade you are welcome to add a recipe on how you did it (in an nx or ng project) and open a PR πŸ™‚

Thanks for the fast reaction and clarification :)

commented

@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 (npx create-nx-workspace@latest). EDIT: Never mind, that package was transparently upgraded to the deprecated 5.0.9 version.

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. In jest.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)'],