jestjs / jest

Delightful JavaScript Testing.
https://jestjs.io
MIT License
44.28k stars 6.47k forks source link

[Bug]: Failed to parse the TypeScript config file with typescript@5.6.2 #15312

Open wtto00 opened 2 months ago

wtto00 commented 2 months ago

Version

29.7.0

Steps to reproduce

After I upgraded typeScript version from 5.5.4 to 5.6.2, my test pipeline execution failed.

My execution failed pipeline is https://github.com/wtto00/android-tools/actions/runs/10907495575/job/30271298092

Expected behavior

jest --detectOpenHandles --verbose executed successfully.

Actual behavior

jest --detectOpenHandles --verbose execution failed, the failure information is as follows:

> @wtto00/android-tools@1.0.5 test E:\projects\github\wtto00\android-tools
> jest --detectOpenHandles --verbose

Error: Jest: Failed to parse the TypeScript config file E:\projects\github\wtto00\android-tools\jest.config.ts
  SyntaxError: Unexpected token 'export'
    at readConfigFileAndSetRootDir (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\jest-config@29.7.0_@types+node@22.5.5_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\jest-config\build\readConfigFileAndSetRootDir.js:116:13)
    at async readInitialOptions (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\jest-config@29.7.0_@types+node@22.5.5_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\jest-config\build\index.js:403:13)
    at async readConfig (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\jest-config@29.7.0_@types+node@22.5.5_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\jest-config\build\index.js:147:48)
    at async readConfigs (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\jest-config@29.7.0_@types+node@22.5.5_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\jest-config\build\index.js:424:26)
    at async runCLI (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\@jest+core@29.7.0_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\@jest\core\build\cli\index.js:151:59)
    at async Object.run (E:\projects\github\wtto00\android-tools\node_modules\.pnpm\jest-cli@29.7.0_@types+node@22.5.5_ts-node@10.9.2_@types+node@22.5.5_typescript@5.6.2_\node_modules\jest-cli\build\run.js:130:37)

Additional context

Related dependency versions:

jest@29.7.0
ts-jest@29.2.5
ts-node@10.9.2
tslib@2.7.0
typescript@5.6.2

Environment

System:
    OS: Windows 11 10.0.22631
    CPU: (6) x64 Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
  Binaries:
    Node: 20.13.1 - ~\AppData\Local\fnm_multishells\11248_1726675469235\node.EXE
    npm: 10.8.1 - ~\AppData\Local\fnm_multishells\11248_1726675469235\npm.CMD
    pnpm: 9.1.1 - ~\AppData\Local\fnm_multishells\11248_1726675469235\pnpm.CMD
  npmPackages:
    jest: ^29.7.0 => 29.7.0
joshuablokland commented 1 month ago

We are having the same issue, strangely enough it is only one module that is failing at our end. The below line inside a jest.config.js file used to work for typescript@5.5.4 and started failing when updating to typescript@5.6.2

transformIgnorePatterns: ['node_modules/(?!p-defer)']

JoostK commented 1 month ago

Could you try renaming the file to jest.config.cts? tsconfig.json targets "module": "NodeNext" and package.json has "type": "module", so TS will emit ESM and I'm wondering whether changing the extension to request CJS would make a difference.

wtto00 commented 1 month ago

Hello @JoostK My config file is jest.config.ts, "module": "NodeNext" in tsconfig.json and "type": "module" in package.json. You can see them in https://github.com/wtto00/android-tools .

After I renamed the file to jest.config.cts, a new error occurred:

> @wtto00/android-tools@1.0.5 test E:\projects\github\wtto00\android-tools
> jest --detectOpenHandles --verbose

 FAIL  spec/start.test.ts
  ● 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:

    E:\projects\github\wtto00\android-tools\spec\start.test.ts:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import Android from '../src/index.js';
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/.pnpm/jest-runtime@29.7.0/node_modules/jest-runtime/build/index.js:1505:14)
legendsland commented 1 month ago

Same here:

` ● 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:

 ..../node_modules/vscode-ws-jsonrpc/lib/index.js:6
export * from './disposable.js';
^^^^^^

SyntaxError: Unexpected token 'export'

  24 | exports.WebSocketClient = void 0;
  25 | const inversify_1 = require("inversify");
> 26 | const vscode_ws_jsonrpc_1 = require("vscode-ws-jsonrpc");
     |                             ^

`

patricklafrance commented 1 month ago

Same:

Error: Jest: Failed to parse the TypeScript config file C:\Dev\wl-squide\packages\core\jest.config.ts
  Error [ERR_INTERNAL_ASSERTION]: This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
manchuck commented 1 month ago

I'm having the same issue, but not with Node 22: https://github.com/Vonage/vonage-node-sdk/actions/runs/10997790768 Forcing TS 5.5.4 resolves this issue

mmomtchev commented 1 month ago

Same issue for me, I have a jest.config.js which transforms some node_modules that are ES6 via transformIgnorePatterns. This does not work anymore since TypeScript 5.6.

I am linking the changelog which mentions a behavior change for ES6 modules, but I really don't understand how this break jest (or ts-jest).

https://devblogs.microsoft.com/typescript/announcing-typescript-5-6/

mmomtchev commented 1 month ago

Ok, I do understand it - here is the precise problem: https://github.com/microsoft/TypeScript/issues/59991

Alas, the answer is "working as intended".

Before 5.6, TypeScript would output whatever it was configured to output. Since 5.6, if the module is a type: module or if the file is a .mjs, TypeScript will output ES6 which jest fails to parse.

mmomtchev commented 1 month ago

Time to go back to the good ol' babel:

transform: {
    '\\.tsx?$': [
        'ts-jest',
        {
            tsconfig: {
                outDir: './.ts-jest'
            }
        }
    ],
    '\\.jsx?$': ['babel-jest', {plugins: ['@babel/plugin-transform-modules-commonjs']}]
},
transformIgnorePatterns: [
    '/node_modules/(?!(yourstuff))'
],
npm install --save-dev babel-jest @babel/core @babel/plugin-transform-modules-commonjs

Keep ts-jest for the TypeScript stuff and use babel for the rest.

manchuck commented 1 month ago

@mmomtchev Yeah, that is another workaround until this is addressed, but it's not ideal. When using Babel, you lose the type checking in your tests. Hopefully, this can be addressed by providing more support for ESM. However, I think that will not happen since Node can support mixing CJS and ESM in the future. Its unlikely we will get this resolved for Node 18 and 20 (which is still in LTS)

mmomtchev commented 1 month ago

No, you still use ts-jest for your TypeScript - with type checking - and babel for the ES6 JS. You still get type checking with this configuration.

patricklafrance commented 1 month ago

@manchuck how do you get it to work with Node 22? Doesn't work for me with Node 22 until I force TS to version 5.5.4.

manchuck commented 1 month ago

@mmomtchev sorry I meant you loose type checking for your test scripts. Yes you still get TS checking for code. Apologies for the mis type

@patricklafrance I didn't do anything it was working just fine with 22. Here is the run that passed in our action: https://github.com/Vonage/vonage-node-sdk/actions/runs/10997790768/job/30534604593

mmomtchev commented 1 month ago

@manchuck why would the rules be different for the tests? Are you tests named *.js? I just changed a type and ts-jest spewed an error.

@patricklafrance he is in a very specific particular case of this issue, because unlike us, he is not transpiling any external node_modules - he is transpiling only his own code. But it is still interesting to know what is different in Node 22.

wtto00 commented 1 month ago
In my project https://github.com/wtto00/android-tools, after I switched to node@22, I found that my test scripts worked fine. typescript node result
v5.5.4 v20
v5.5.4 v22
v5.6.2 v20
v5.6.2 v22

However, it is still unclear why node20 cannot work properly while node22 can.

manchuck commented 1 month ago

@mmomtchev yes ts-jest will run it through typescript. Babel will not and you lose type checking. It is described in the documentation https://jestjs.io/docs/getting-started#using-typescript

However, there are some caveats to using TypeScript with Babel. Because TypeScript support in Babel is purely transpilation, Jest will not type-check your tests as they are run. If you want that, you can use ts-jest instead, or just run the TypeScript compiler tsc separately (or as part of your build process).

In terms of node 22 it could be how I'm running the tests with NODE_NO_WARNINGS=1 NODE_OPTIONS=\"--experimental-vm-modules\" set. Maybe it has something to do with that? I didn't spend too much time looking into it as we really don't need ts 5.6

mmomtchev commented 1 month ago

@manchuck now it is because it is described in the documentation? For both the tests and the code? Or only for the code without the tests? :smile:

This configuration runs TypeScript code through ts-jest and ES6 code through babel - so that you have type checking.

manchuck commented 1 month ago

@mmomtchev Babel will not type check tests. I don't know how else to explain it. I recently reviewed the entire code base to ensure that tests were correctly typed by removing babel: https://github.com/Vonage/vonage-node-sdk/commit/e361fbe755ee5bd4b264e5f7e41900624c7d9f25

Babel will not type check tests. It will type check code. The documentation on that is correct.

mmomtchev commented 1 month ago

Yes, but so is my statement that ts-jest and not babel is used for all files ending in .ts.

github-actions[bot] commented 3 weeks ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.