Closed ahnpnl closed 3 years ago
@ahnpnl Sorry, I didn't properly look at this ticket when starting to work on it yesterday:
https://github.com/hedefalk/ts-jest/commit/f488ab64929a16deccd58d02e668cf5b254790e0
As mentioned in the other thread, I think we have a problem that the extension that jest switches on is not the extension we output from ts-jest, but will be the input file's extension (.ts). At least it seemed that way when I debugged it, I'll double check…
yep, all I know is transformer only delivers compiled js but nothing is mentioned about file extension. That might need to investigate.
It is still unclear how transformer should adopt to esm support. Need more guidance from jest team
ESM works now in ts-node very well since v9.1.0. Would be great to have ts-jest support ESM too. It's the last tool in my toolbox to support esm :)
I just tested the ts-jest master with jest v27.0.0-next.2. After
"jest": {
"testEnvironment": "node",
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest"
},
"extensionsToTreatAsEsm": [".ts"],
"testMatch": [
"**/tests/**/*.spec.ts"
]
}
"target": "es2018",
"module": "esnext",
"esModuleInterop": true,
node --experimental-vm-modules node_modules/jest/bin/jest.js
everything works great with my esnext tests + esnext dependencies. ✌️
ESM support for isolatedModules: true
was out in 27.0.0-next.2.
isolatedModules: false
will come later.
finished in 27.0.0-next.3
Hi, I recently working on a project that use typescript, jest and ts-jest. When I run jest. It give me this error:
__tests__/someTypescriptCode.test.ts:1:25 - error TS2691: An import path cannot end with a '.ts' extension. Consider importing '../src/someTypescriptCode' instead.
1 import information from '../src/someTypescriptCode.ts';
I had explicitly install ts-jest@27.0.0-next.3
and jest@27.0.0-next.2
. Execute jest with node --experimental-vm-modules node_modules/jest/bin/jest.js
This is how my jest.config.js file look like
// jest.config.js
export default {
"roots": [
"<rootDir>"
],
"testMatch": [
"**/__tests__/**/*.+(ts|tsx|js)",
"**/?(*.)+(spec|test).+(ts|tsx|js)"
],
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest"
},
"testEnvironment": 'node',
"extensionsToTreatAsEsm": [".ts"]
}
My tsconfig.json:
{
"compilerOptions": {
"target": "ES2018",
"module": "ESNEXT",
"outDir": "./build",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["./src"],
"exclude": ["node_modules", "**/*.test.ts"]
}
Please help. Thank you.
Hi, to use ESM you need to follow doc https://kulshekhar.github.io/ts-jest/docs/next/guides/esm-support
Besides, the error comes from TypeScript itself. I'm not sure why. It’s better that your import path shouldn’t contain “.ts” extension.
Hi, to use ESM you need to follow doc https://kulshekhar.github.io/ts-jest/docs/next/guides/esm-support
Besides, the error comes from TypeScript itself. I'm not sure why. It’s better that your import path shouldn’t contain “.ts” extension.
It did work if I remove ".ts". But my actual headache is something like this: I have
// codeA.ts;
export default (arg: string): boolean => {
// some implementation
}
// codeB.ts
import codeA from './codeA.js'; // ".js" not typo, it work fine after "tsc" transpile, but jest always complaint
export const someFunction = (): void => {
// some more code
}
// codeB.test.ts
import * as Bcode from './codeB';
Error occur when jest execution hit import codeA from './codeA.js'
inside codeB.ts
Which error do you get ?
Maybe you can share your repo here
Which error do you get ?
Maybe you can share your repo here
👍, but let me remove all unrelated codes first. Thank you our willingness to help 😊
Sorry for the delay respond, I was trying to re-create the same error, here is my repo https://github.com/koonfoon/ts-jest-code-test. This is not my actual project, but is very similar to what I am trying to test with jest. Thanks
Can I ask what is the recommended way to import local .ts
files?
I understood the convention is to:
// Import as ".js" even though the source file is ".ts"
import file from "./file.js"
Unless I missed something, that will fail with:
Cannot find module './file.js' from 'src/callingFile.spec.ts'
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:311:11)
I got it working by stripping off the .js
with moduleMapper
in my jest.config.ts
:
moduleNameMapper: {
"(.*)\\.js$": "$1",
},
but I guess this will fail on the same ambiguous edge cases the forcing .js
is meant to solve.
Happy to create a more minimal repo for this but I think my main question is to just understand the recommended way to import other local .ts
files.
@koonfoon this will presumably solve your problem but I'm not sure if it will solve it in the right way :sweat_smile:
@gadicc you simply import the TS files as usual, omitting the file extension.
Ok thanks, got it! And thanks for the miraculously fast reply 😅 Have a great weekend 🎉
On Fri, 30 Apr 2021, 18:21 Marc J. Schmidt, @.***> wrote:
@gadicc https://github.com/gadicc you simply import the TS files as usual, omitting the file extension.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kulshekhar/ts-jest/issues/1709#issuecomment-830170644, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAC5IGRZEW7CRFGVUCKH3VTTLLDJBANCNFSM4NSLIQFQ .
Hi @gadicc thank you for your suggestion, will try it out.
you simply import the TS files as usual, omitting the file extension.
This doesn't make sense to me.
In an ESM project, imports will end with .js. Even when I omit the file extension in my test files, the code under test will import other modules, using .js
files extensions. In other words:
// file: a.spec.ts
import * as a from './a'; // works
// file: a.ts
import * as b from './b.js'; // "Cannot find module './b.js' from './a.ts'
For what it's worth, @gadicc workaround seems to work for me.
Hi @tstelzer I did try @gadicc suggested method, it worked fine when I only import local codes/modules that are written by me. But when I import others npm packages/dependencies. It will start giving me errors again. I suspect moduleNameMapper
blindly resolved import's from others npm packages/dependencies too. I will try to re-create the error again and post it here. It had been a month since the last time I try to work on this issue.
@koonfoon, probably the following regexp will fix that for you but I haven't tested:
moduleNameMapper: {
"^(\\./.*)\\.js$": "$1",
},
It will only match imports starting with ./
(and ending with .js
) and so ignore imports from packages.
I reproduced the original issue in https://github.com/tstelzer/ts-jest-playground
Running npm test
produces:
Cannot find module './a.js' from 'src/a.spec.ts'
> 1 | import * as a from './a.js';
| ^
2 |
3 | describe('a', () => {
4 | test('foo', () => {
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:311:11)
at Object.<anonymous> (src/a.spec.ts:1:1)
(edit) By the way, as to my intentions:
The issue you are seeing about “Cannot find module”, it is linked to Jest default resolver. This is not something for ts-jest
because ts-jest
is a Jest transformer, which only compiles ts to js. You should bring this error to https://github.com/facebook/jest/issues/9430
Thanks, @ahnpnl, for clarifying. To save others some time I'm going to pull out a few quotes from that issue:
From SimenB (Jest author/collaborator) in this comment:
yeah, remove the extension from your import. Jest doesn't operate on the "virtual" .js file, but the
ts
file directly. You'll also need https://jestjs.io/docs/next/configuration#extensionstotreatasesm-arraystring.Feel free to open up a new issue about resolving the
js
file, we'll probably need it (somehow) for proper interop with other tools (using the.js
extension is whatts-node
says to do even though the file does not exist)
From cspotcode (Jest contributor) in this comment:
A quick note,
ts-node
also supports extensionless imports as long as you've enabled the correct node flag--experimental-specifier-resolution=node
This extensionless resolution behavior is implemented by node, so if you don't enable it, node will throw errors, and we can't stop that. Even ifts-node
papered over this wrinkle, pre-compiled code would fail outside ofts-node
, so this would be counter-productive.When users do not want to enable this flag, we recommend adding the
.js
extension because otherwise TS's language service will raise an error in their code editor, outside ofts-node
. Even ifts-node
supported .ts extensions, any typechecking outside of ts-node would throw errors, so this would be counter-productive.tl;dr; we recommend the options that will keep a project happy external to
ts-node
.
There are a few other references in the thread but I believe these two are the most pertinent for now.
@gadicc both of your moduleNameMapper
regex work for me. Actually I had a Q&A and ended up @ahnpnl gave me the same idea, but I am not that familiar with regex😅, so this is my regex '(.*).js': ['$1'],
before yours posts.😅
The regular expression @gadicc mentioned (^(\\./.*)\\.js$
) only matches paths starting with ./
, however I suppose you should also match ../
.
This is a slight modification that works for me:
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
}
It matches paths that either start with ./
or ../
and end with .js
.
Does this also work with the imports from packages you mentioned? I am not having any problems so far.
thanks very much @gadicc and @puchm for the moduleNameWrapper
-based solution!
@ahnpnl i came across your comment in #1057 (https://github.com/kulshekhar/ts-jest/issues/1057#issuecomment-803642747) and this issue while trying to figure out the right way to create a typescript "type": "module"
package that uses ts-jest. one thing that stood out for me is this explanation:
Actually, the preset means "A Jest configuration". This preset includes a transformer, which compiles
ts
intojs
. I know it's a bit hard to understand what's going on in internalts-jest
.
using moduleNameWrapper
seems like a reasonable solution to enable testing typescript ESM packages with ts-jest
, and it’s a part of “Jest configuration”. this makes me think that if feasible, it would be a reasonable thing to include in the ESM presets (e.g. ts-jest/presets/default-esm
, the one i am using). and if not, i definitely think it warrants a mention in the docs. for the latter, i made a PR: https://github.com/kulshekhar/ts-jest/pull/2922
Does debugging work on Windows with VSCode (for typescript) if the test script is configured with --experimental-vm-modules ? "test" entry in package.json: "test": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest --runInBand",
🚀 Feature Proposal
Jest is working on supporting ESM https://github.com/facebook/jest/issues/9430 . We should consider lift up the hardcoded
target: commonjs
at some points.Related discussion about detecting whether a file is
esm
orcommonjs
can be found here https://github.com/facebook/jest/issues/9860Related issue: #1174
Motivation
Let
ts-jest
users as well asjest
users take part in the ESM support development and testing.