ts-jest: Tests fail when using TypeScript project references
š Bug Report
Iām in the process of migrating one of my projects to use Typescript project references, but after migration the tests that validated error types failed.
Iāve created a repo that has one directory with a very small project where tests succeed, and one directory with a project using typescript projects references where the tests fail. The projects are identical with the exception of project references. Iām not saying that ts-jest is to blame. It could as well be my understanding of project references or jest.
To Reproduce
git clone https://github.com/FantasticFiasco/jest-error-type-issue.git
cd jest-error-type-issue/does-not-work
yarn
yarn test
Expected behavior
I would expect the test to pass, because in the same git repository there is a directory called works with an identical project except the project references that has a test that passes.
Link to repo (highly encouraged)
https://github.com/FantasticFiasco/jest-error-type-issue
Debug log:
{"context":{"allowJs":false,"logLevel":20,"namespace":"jest-preset","package":"ts-jest","version":"25.5.1"},"message":"creating jest presets not handling JavaScript files","sequence":1,"time":"2020-05-15T16:59:54.105Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"25.5.1"},"message":"creating Importer singleton","sequence":2,"time":"2020-05-15T16:59:55.006Z"}
{"context":{"allowJs":false,"logLevel":20,"namespace":"jest-preset","package":"ts-jest","version":"25.5.1"},"message":"creating jest presets not handling JavaScript files","sequence":3,"time":"2020-05-15T16:59:55.010Z"}
{"context":{"actualVersion":"25.5.4","expectedVersion":">=25 <26","logLevel":20,"namespace":"versions","package":"ts-jest","version":"25.5.1"},"message":"checking version of jest: OK","sequence":4,"time":"2020-05-15T16:59:55.011Z"}
{"context":{"baseOptions":{},"logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"25.5.1"},"message":"created new transformer","sequence":5,"time":"2020-05-15T16:59:55.011Z"}
{"context":{"fileName":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/test/foo.spec.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"config":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/private/var/folders/cl/yqb0znw56dj17l06y_45rzx40000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{"computeSha1":false,"providesModuleNodeModules":[],"throwOnModuleCollision":false},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","ts","tsx","node"],"moduleNameMapper":[],"modulePathIgnorePatterns":[],"name":"065014f8040ebe756b2da8ebc80e3c0a","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","roots":["/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work"],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.[jt]s?(x)","**/?(*.)+(spec|test).[tj]s?(x)"],"testPathIgnorePatterns":["/node_modules/"],"testRegex":[],"testRunner":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/ts-jest/dist/index.js",{}]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"instrument":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","supportsDynamicImport":false,"supportsStaticESM":false},"transformerId":1,"version":"25.5.1"},"message":"computing cache key for /Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/test/foo.spec.ts","sequence":6,"time":"2020-05-15T16:59:55.012Z"}
{"context":{"logLevel":30,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"25.5.1"},"message":"no matching config-set found, creating a new one","sequence":7,"time":"2020-05-15T16:59:55.012Z"}
{"context":{"config":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/private/var/folders/cl/yqb0znw56dj17l06y_45rzx40000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{"computeSha1":false,"providesModuleNodeModules":[],"throwOnModuleCollision":false},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","ts","tsx","node"],"moduleNameMapper":[],"modulePathIgnorePatterns":[],"name":"065014f8040ebe756b2da8ebc80e3c0a","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","roots":["/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work"],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.[jt]s?(x)","**/?(*.)+(spec|test).[tj]s?(x)"],"testPathIgnorePatterns":["/node_modules/"],"testRegex":[],"testRunner":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/ts-jest/dist/index.js",{}]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"backports","package":"ts-jest","transformerId":1,"version":"25.5.1"},"message":"backporting config","sequence":8,"time":"2020-05-15T16:59:55.012Z"}
{"context":{"jestConfig":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/private/var/folders/cl/yqb0znw56dj17l06y_45rzx40000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{"ts-jest":{}},"haste":{"computeSha1":false,"providesModuleNodeModules":[],"throwOnModuleCollision":false},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","ts","tsx","node"],"moduleNameMapper":[],"modulePathIgnorePatterns":[],"name":"065014f8040ebe756b2da8ebc80e3c0a","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","roots":["/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work"],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.[jt]s?(x)","**/?(*.)+(spec|test).[tj]s?(x)"],"testPathIgnorePatterns":["/node_modules/"],"testRegex":[],"testRunner":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/ts-jest/dist/index.js",{}]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"25.5.1"},"message":"normalized jest config","sequence":9,"time":"2020-05-15T16:59:55.013Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsJestConfig":{"compiler":"typescript","diagnostics":{"ignoreCodes":[6059,18002,18003],"pretty":true,"throws":true},"isolatedModules":false,"packageJson":{"kind":"file"},"transformers":[],"tsConfig":{"kind":"file"}},"version":"25.5.1"},"message":"normalized ts-jest config","sequence":10,"time":"2020-05-15T16:59:55.013Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"25.5.1"},"message":"babel is disabled","sequence":11,"time":"2020-05-15T16:59:55.015Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","requireResult":{"exists":true,"given":"typescript","path":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/typescript/lib/typescript.js"},"version":"25.5.1"},"message":"loaded module typescript","sequence":12,"time":"2020-05-15T16:59:55.169Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"25.5.1"},"message":"patching typescript","sequence":13,"time":"2020-05-15T16:59:55.169Z"}
{"context":{"actualVersion":"3.9.2","expectedVersion":">=3.4 <4","logLevel":20,"namespace":"versions","package":"ts-jest","version":"25.5.1"},"message":"checking version of typescript: OK","sequence":14,"time":"2020-05-15T16:59:55.169Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsConfigFileName":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/tsconfig.json","version":"25.5.1"},"message":"readTsConfig(): reading /Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/tsconfig.json","sequence":15,"time":"2020-05-15T16:59:55.169Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsconfig":{"compileOnSave":false,"configFileSpecs":{"filesSpecs":[],"wildcardDirectories":{}},"errors":[],"fileNames":[],"options":{"configFilePath":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/tsconfig.json","declaration":false,"inlineSourceMap":false,"inlineSources":true,"module":1,"noEmit":false,"removeComments":false,"sourceMap":true,"target":1},"projectReferences":[{"originalPath":"./src","path":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/src"},{"originalPath":"./test","path":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/test"}],"raw":{"compileOnSave":false,"compilerOptions":{},"files":[],"references":[{"path":"./src"},{"path":"./test"}]},"typeAcquisition":{"enable":false,"exclude":[],"include":[]},"wildcardDirectories":{}},"version":"25.5.1"},"message":"normalized typescript config","sequence":16,"time":"2020-05-15T16:59:55.175Z"}
{"context":{"fileName":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/src/foo.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"config":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/private/var/folders/cl/yqb0znw56dj17l06y_45rzx40000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{"computeSha1":false,"providesModuleNodeModules":[],"throwOnModuleCollision":false},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","ts","tsx","node"],"moduleNameMapper":[],"modulePathIgnorePatterns":[],"name":"065014f8040ebe756b2da8ebc80e3c0a","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","roots":["/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work"],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.[jt]s?(x)","**/?(*.)+(spec|test).[tj]s?(x)"],"testPathIgnorePatterns":["/node_modules/"],"testRegex":[],"testRunner":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/node_modules/ts-jest/dist/index.js",{}]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"instrument":false,"rootDir":"/Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work","supportsDynamicImport":false,"supportsStaticESM":false},"transformerId":1,"version":"25.5.1"},"message":"computing cache key for /Users/mattiask/code/open-source/temp/jest-error-type-issue/does-not-work/src/foo.ts","sequence":17,"time":"2020-05-15T16:59:55.178Z"}
envinfo
System:
OS: macOS Catalina v10.15.4
Npm packages:
jest: v25.5.4
ts-jest: v25.5.1
typescript: v3.9.2
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 17
- Comments: 38
Commits related to this issue
- Specify tsconfig for ts-jest Unfortunately ts-jest cannot automatically resolve the tsconfig file if we rename it to something else. (See kulshekhar/ts-jest#1648) — committed to Folkwise-io/MintbeanplatformV3-backend by jpqy 4 years ago
- Specify tsconfig for ts-jest Unfortunately ts-jest cannot automatically resolve the tsconfig file if we rename it to something else. (See kulshekhar/ts-jest#1648) — committed to Folkwise-io/MintbeanplatformV3-backend by jpqy 4 years ago
- Add simple test for prepareStory Note that without extending the top-level tsconfig.json from tsconfig.base.json, the right compiler options weren't being applied for the tests, even though they are ... — committed to chanzuckerberg/frontend-libs by ahuth 4 years ago
- Add simple test for prepareStory Note that without extending the top-level tsconfig.json from tsconfig.base.json, the right compiler options weren't being applied for the tests, even though they are ... — committed to chanzuckerberg/frontend-libs by ahuth 4 years ago
- Add simple test for prepareStory Note that without extending the top-level tsconfig.json from tsconfig.base.json, the right compiler options weren't being applied for the tests, even though they are ... — committed to chanzuckerberg/frontend-libs by ahuth 4 years ago
@rhyek same.
if i run
yarn workspace subproject1 build, and then in the subproject1 folderās package.json i definebuildto do atsc -b tsconfig.subproject1.json, where this tsconfig containsreferencesto subproject2, which has its own package.json and tsconfig etc, then, everything compiles, all the dist folders are there, and my jest tests, located in subproject1, work just fine.if i do not build myself, then it complains
Cannot find module 'subproject1' or its corresponding type declarations., regardless of whether or not I attempt to usemoduleNameMapperin subproject1ās jest config.So, bottom line is that it seems that ts-jest is not doing what tsc -b would do, so when in watch mode, i really suffer.
I know this is an old issue, but if anyone else is running into similar problems⦠I just made this on Jest config and it worked for me:
I am going through exactly what @ahnpnl described below. I am posting my use case here in case it is helpful.
I have one monorepo with a package called
commonand one calledui. Thecommonpackage uses absolute imports inside of itself. Theuiuses thecommonpackage, and has some tests inside that depends oncommon.When I try to run the tests from
uipackage, it is unable to understand the absolute imports that thecommonpackage uses inside itself. Ifcommonās tsconfig was properly read, I guess it would work.@FantasticFiasco what did the trick? I couldnāt see any actionables in the two links that @ahnpnl posted. Iām trying to leverage the new āSolution Styleā config as introduced in https://github.com/microsoft/TypeScript/pull/37239, so I have a
tsconfig.jsonfile that looks like this:But when I run my tests they all fail because
ts-jestdoesnāt seem to recognize that the compiler options for each test should be governed by one oftsconfig.foo.jsonortsconfig.bar.json.I want to make clear something:
ts-jestcannot behave like TypeScripttsc -b. The reason ists-jestis a Jest transformer. We only transpiletstojsbased on whatjest-runtimepasses in. This processing way is different fromtsc -bwheretsccontrols the whole project.We can still support project references but maybe only partially and definitely wonāt be exact the same like
tsc -bdoes. In the meantime, you can trymoduleNameMapperto suit your needs.I hope this makes clear to everyone the difference between
jest+ts-jestvs TypeScripttscand your expectations.@JakeGinnivan thanks a lot for the brainstorming help. Iād like to separate the 2 terms here:
jest projectsvsTypeScript project referencesto deal with them separately. I agree that in the end,ts-jestshould support both.Overall, these 2 work almost similar. However, the way
ts-jestworks based on how jest executes tests. Therefore, actually point 1 should be a bit more details besides your explanation above:ts-jeststill needs to behave liketsc -b:It needs to gather compiler options from each individual
tsconfig.jsonlocates in each referenced project (defined inprojectReferences).Detect the current processing file belongs to which referenced projects, then compile using the correct referenced projectās compiler options.
moduleNameMapperis a sort of partially related to this topic. Once the compiling with correct referenced projectās compiler options is solved,moduleNameMapperwill be easier to solve.In this scenario,
jestwill execute tests for each project using that projectās jest config associated withts-jestconfig.I did a small test for this scenario. The project I have contains
project-1,project-2andshare.project-1andproject-2are jest projects and donāt haveprojectReferencesin eachtsconfig.json.shareis just a normal directory to contain shared codes. Here are how things execute:Jest run tests for
project-1.ts-jestcompiles all the files needed inproject-1for test run, include file inshareas well. Thetsconfig.jsonofproject-1is used.Jest run tests for
project-2.ts-jestcompiles all the files needed inproject-2for test run, include file inshareas well. Thetsconfig.jsonofproject-2is also used.This means when using jest config
projects,jestwill automatically create different instance of thets-jest. So regardless usingprojectsor not usingprojects,jestguarantee that tests in each project run in an sandbox environment. Therefore we only need to take care of resolving correcttsconfig.json.If
tsconfig.jsonfromproject-1/project-2containsprojectReferencesto somewhere,ts-jestalso needs to do the same like scenario 1, which also looks fortsconfig.jsonof those referenced projects and compile files with the correct compiler options.Currently, jest transformer doesnāt support async, neither TypeScript
Program, everything is processed on demand and sequentially.@FantasticFiasco that repo uses a workaround in
jest.config.jsto get around the fact thatts-jestdoes not automatically inherit the correct TS config for any given file:But that is a workaround which indicates an underlying bug, and not one that can be applied to my setup either. Itās frustrating to see this and other similar issues (such as https://github.com/kulshekhar/ts-jest/issues/766) be closed when theyāre still reproducible, simply because some people have found a workaround which works for them.
depending on what underlying typescript api
ts-jestis using, some flag is probably needed to be specified in thejest config, similar to what thetsc --buildflag essentially enforces.e.g.
ts-loaderforwebpackprovides a config setting for this:projectReferences: trueissue: https://github.com/TypeStrong/ts-loader/issues/1005
PR: https://github.com/TypeStrong/ts-loader/pull/935
I can help with a repro if nothing else, Iāll look into that now.
Iām also running into this problem. All my tests are failing after migrating to TypeScript project references. It would be nice to have a fix for this.
Hi,
So after spending several hours on this - I was able to make this work in my monorepo. This is my jest.config.ts, hopefully it helps others here:
Note - what did the trcik as specifying transform for each project, and not having a top level testRegex etc. Also, although I have tsconfig.json files in each sub-project that extend the baseline one at the monorepoās root, there doesnāt appear to be a way to force ts-jest to actually pick these up correctly. Hence the need to override the globals.
No thatās my point exactly: the root
tsconfig.jsonfile is a valid config target. Thatās basically one of the motivations of āSolution Styleā configs (per microsoft/TypeScript#37239) in the first place, so that tools like this (and IDEās linter plugins etc) which derive their entire project-config from a single roottsconfig.jsonfile can have different settings for different files/directories.Now, for example, I can have different configs for my
fooandbardirectories, and my IDE is informed of whether to use the config intsconfig.foo.jsonortsconfig.bar.json, not because I explicitly told it so, but because it can derive that information from a single roottsconfig.jsonfile.Otherwise I have to run
jest + ts-jestonce for myfoodirectory (withfoo.config.json) and once more for mybardirectory (withbar.config.json). Despite the fact that runningtsc -b --project=tsconfig.jsoncompiles correctly etc.This one might be related to your case https://github.com/microsoft/TypeScript/pull/37239
In general, ts-jest uses typescript api to read tsconfig and resolves the config to fetch to typescript compiler. In your case, it cannot find enough configs to make tests pass.
Your case is similar to #766