kulshekhar/ts-jest

Compiler options not working as expected when using project references

OliverJAsh opened this issue · 36 comments

Issue :

Full reproduction case

Expected behavior :

I have three TS projects:

  • tsconfig-src.json
  • tsconfig-tests.json
  • tsconfig.json which references both of the above (using TypeScript's new "project references" feature)

When running jest, it should read compiler options from tsconfig.json.

Because tsconfig.json includes no files for itself but just references other projects, ts-jest should read its compiler options from the project reference that corresponds to any given file.

For example, tsconfig.json references the tsconfig-tests.json project:

{
  "references": [
    {
      "path": "./tsconfig-tests.json"
    }
  ]
}

In turn, tsconfig-tests.json includes all test files:

{
  "include": ["**/__tests__/**/*"]
}

Given this example, I expect any test file matching the tests TS project (tsconfig-tests.json, which includes **/__tests__/**/*) to use compiler options for that TS project.

Actual behaviour

Looking at the logs, I can see tsconfig.json is used. However, compilerOptions is read from tsconfig.json, not tsconfig-tests.json.

I have verified this:

  • When I add compiler options to tsconfig.json, ts-jest uses them.
  • When I add compiler options to tsconfig-tests.json, ts-jest does not use them.

Debug log:

log file content
# content of ts-jest.log :
{"context":{"allowJs":false,"logLevel":20,"namespace":"jest-preset","package":"ts-jest","version":"23.10.1"},"message":"creating jest presets not handling JavaScript files","sequence":1,"time":"2018-09-26T16:17:30.904Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"23.10.1"},"message":"creating Importer singleton","sequence":2,"time":"2018-09-26T16:17:32.262Z"}
{"context":{"allowJs":false,"logLevel":20,"namespace":"jest-preset","package":"ts-jest","version":"23.10.1"},"message":"creating jest presets not handling JavaScript files","sequence":3,"time":"2018-09-26T16:17:32.268Z"}
{"context":{"actualVersion":"23.6.0","expectedVersion":">=22 <24","logLevel":20,"namespace":"versions","package":"ts-jest","version":"23.10.1"},"message":"checking version of jest: OK","sequence":4,"time":"2018-09-26T16:17:32.271Z"}
{"context":{"baseOptions":{},"logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"created new transformer","sequence":5,"time":"2018-09-26T16:17:32.271Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/__tests__/add.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"instrument":false,"rootDir":"/Users/OliverJAsh/Development/temp/jest-ts-project-references"},"transformerId":1,"version":"23.10.1"},"message":"computing cache key for /Users/OliverJAsh/Development/temp/jest-ts-project-references/src/__tests__/add.ts","sequence":6,"time":"2018-09-26T16:17:32.274Z"}
{"context":{"logLevel":30,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"no matching config-set found, creating a new one","sequence":7,"time":"2018-09-26T16:17:32.275Z"}
{"context":{"config":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/var/folders/j9/5w0fkxkx5y71q82qxpbcr_l80000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/OliverJAsh/Development/temp/jest-ts-project-references","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"filter":null,"forceCoverageMatch":[],"globals":{},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","node","ts","tsx"],"moduleNameMapper":{},"modulePathIgnorePatterns":[],"name":"16fd8dbb7736f57ff030f33e19558e92","prettierPath":null,"resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/Users/OliverJAsh/Development/temp/jest-ts-project-references","roots":["/Users/OliverJAsh/Development/temp/jest-ts-project-references"],"runner":"jest-runner","setupFiles":[],"setupTestFrameworkScriptFile":null,"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.js?(x)","**/?(*.)+(spec|test).js?(x)","**/__tests__/**/*.ts?(x)","**/?(*.)+(spec|test).ts?(x)"],"testPathIgnorePatterns":["/Users/OliverJAsh/Development/temp/jest-ts-project-references/target/"],"testRegex":"","testRunner":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/ts-jest/dist/index.js"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"backports","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"backporting config","sequence":8,"time":"2018-09-26T16:17:32.275Z"}
{"context":{"jestConfig":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"/var/folders/j9/5w0fkxkx5y71q82qxpbcr_l80000gn/T/jest_dx","clearMocks":false,"coveragePathIgnorePatterns":["/node_modules/"],"cwd":"/Users/OliverJAsh/Development/temp/jest-ts-project-references","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"filter":null,"forceCoverageMatch":[],"globals":{"ts-jest":{}},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":["node_modules"],"moduleFileExtensions":["js","json","jsx","node","ts","tsx"],"moduleNameMapper":{},"modulePathIgnorePatterns":[],"name":"16fd8dbb7736f57ff030f33e19558e92","prettierPath":null,"resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"/Users/OliverJAsh/Development/temp/jest-ts-project-references","roots":["/Users/OliverJAsh/Development/temp/jest-ts-project-references"],"runner":"jest-runner","setupFiles":[],"setupTestFrameworkScriptFile":null,"skipFilter":false,"snapshotSerializers":[],"testEnvironment":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/jest-environment-node/build/index.js","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":["**/__tests__/**/*.js?(x)","**/?(*.)+(spec|test).js?(x)","**/__tests__/**/*.ts?(x)","**/?(*.)+(spec|test).ts?(x)"],"testPathIgnorePatterns":["/Users/OliverJAsh/Development/temp/jest-ts-project-references/target/"],"testRegex":"","testRunner":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/jest-jasmine2/build/index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/ts-jest/dist/index.js"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"normalized jest config","sequence":9,"time":"2018-09-26T16:17:32.276Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsJestConfig":{"compiler":"typescript","diagnostics":{"ignoreCodes":[6059,18002,18003],"pretty":true,"throws":true},"isolatedModules":false,"transformers":[],"tsConfig":{"kind":"file"}},"version":"23.10.1"},"message":"normalized ts-jest config","sequence":10,"time":"2018-09-26T16:17:32.276Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"babel is disabled","sequence":11,"time":"2018-09-26T16:17:32.277Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"23.10.1"},"message":"loaded module typescript","sequence":12,"time":"2018-09-26T16:17:32.574Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"23.10.1"},"message":"patching typescript","sequence":13,"time":"2018-09-26T16:17:32.574Z"}
{"context":{"actualVersion":"3.0.3","expectedVersion":">=2.7 <4","logLevel":20,"namespace":"versions","package":"ts-jest","version":"23.10.1"},"message":"checking version of typescript: OK","sequence":14,"time":"2018-09-26T16:17:32.575Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsConfigFileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig.json","version":"23.10.1"},"message":"readTsConfig(): reading /Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig.json","sequence":15,"time":"2018-09-26T16:17:32.575Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsconfig":{"input":{"compilerOptions":{},"files":[],"include":[],"references":[{"path":"./tsconfig-src.json"},{"path":"./tsconfig-tests.json"}]},"resolved":{"compileOnSave":false,"configFileSpecs":{"filesSpecs":[],"includeSpecs":[],"validatedIncludeSpecs":[],"wildcardDirectories":{}},"errors":[{"category":1,"code":18002,"messageText":"The 'files' list in config file '/Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig.json' is empty."}],"fileNames":[],"options":{"configFilePath":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig.json","declaration":false,"inlineSourceMap":false,"inlineSources":true,"module":1,"noEmit":false,"outDir":"$$ts-jest$$","removeComments":false,"sourceMap":true,"target":1},"projectReferences":[{"originalPath":"./tsconfig-src.json","path":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig-src.json"},{"originalPath":"./tsconfig-tests.json","path":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/tsconfig-tests.json"}],"raw":{"compileOnSave":false,"compilerOptions":{},"files":[],"include":[],"references":[{"path":"./tsconfig-src.json"},{"path":"./tsconfig-tests.json"}]},"typeAcquisition":{"enable":false,"exclude":[],"include":[]},"wildcardDirectories":{}}},"version":"23.10.1"},"message":"normalized typescript config","sequence":16,"time":"2018-09-26T16:17:32.583Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"instrument":false,"rootDir":"/Users/OliverJAsh/Development/temp/jest-ts-project-references"},"transformerId":1,"version":"23.10.1"},"message":"computing cache key for /Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","sequence":17,"time":"2018-09-26T16:17:32.597Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"instrument":false},"transformerId":1,"version":"23.10.1"},"message":"processing /Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","sequence":18,"time":"2018-09-26T16:17:32.597Z"}
{"context":{"logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"creating typescript compiler (language service)","sequence":19,"time":"2018-09-26T16:17:32.598Z"}
{"context":{"cacheDirectory":"/var/folders/j9/5w0fkxkx5y71q82qxpbcr_l80000gn/T/jest_dx/ts-jest-12649e7f15d09e17a4fbf3203d8f5538cdd2552e","logLevel":20,"namespace":"config","package":"ts-jest","version":"23.10.1"},"message":"will use file caching","sequence":20,"time":"2018-09-26T16:17:32.598Z"}
{"context":{"logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"creating language service","sequence":21,"time":"2018-09-26T16:17:32.599Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readThrough(): cache miss","sequence":22,"time":"2018-09-26T16:17:32.601Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getOutput(): compiling using language service","sequence":23,"time":"2018-09-26T16:17:32.602Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"updateMemoryCache()","sequence":24,"time":"2018-09-26T16:17:32.602Z"}
{"context":{"cacheHit":true,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache hit","sequence":25,"time":"2018-09-26T16:17:32.602Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":26,"time":"2018-09-26T16:17:32.615Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":27,"time":"2018-09-26T16:17:32.617Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/add.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":28,"time":"2018-09-26T16:17:32.619Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":29,"time":"2018-09-26T16:17:32.622Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/index.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":30,"time":"2018-09-26T16:17:32.623Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/common.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":31,"time":"2018-09-26T16:17:32.627Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":32,"time":"2018-09-26T16:17:32.644Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/array.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":33,"time":"2018-09-26T16:17:32.645Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/collection.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":34,"time":"2018-09-26T16:17:32.719Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/date.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":35,"time":"2018-09-26T16:17:32.750Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/function.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":36,"time":"2018-09-26T16:17:32.751Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/lang.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":37,"time":"2018-09-26T16:17:32.796Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/math.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":38,"time":"2018-09-26T16:17:32.816Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/number.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":39,"time":"2018-09-26T16:17:32.820Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/object.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":40,"time":"2018-09-26T16:17:32.825Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/seq.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":41,"time":"2018-09-26T16:17:32.869Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/string.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":42,"time":"2018-09-26T16:17:32.872Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/common/util.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":43,"time":"2018-09-26T16:17:32.880Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":44,"time":"2018-09-26T16:17:32.913Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":45,"time":"2018-09-26T16:17:32.914Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":46,"time":"2018-09-26T16:17:32.916Z"}
{"context":{"call":null,"logLevel":10,"namespace":"ts:serviceHost","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"readFile","sequence":47,"time":"2018-09-26T16:17:32.917Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/jest/index.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":48,"time":"2018-09-26T16:17:32.919Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/typescript/lib/lib.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":49,"time":"2018-09-26T16:17:32.936Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/typescript/lib/lib.es5.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":50,"time":"2018-09-26T16:17:32.937Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/typescript/lib/lib.dom.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":51,"time":"2018-09-26T16:17:32.982Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/typescript/lib/lib.webworker.importscripts.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":52,"time":"2018-09-26T16:17:33.139Z"}
{"context":{"cacheHit":false,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/typescript/lib/lib.scripthost.d.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache miss","sequence":53,"time":"2018-09-26T16:17:33.142Z"}
{"context":{"call":null,"logLevel":20,"namespace":"ts-hoisting","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"visitSourceFileNode(): hoisting","sequence":54,"time":"2018-09-26T16:17:33.516Z"}
{"context":{"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":20,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getOutput(): computing diagnostics","sequence":55,"time":"2018-09-26T16:17:33.534Z"}
{"context":{"cacheHit":true,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache hit","sequence":56,"time":"2018-09-26T16:17:33.534Z"}
{"context":{"cacheHit":true,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache hit","sequence":57,"time":"2018-09-26T16:17:33.535Z"}
{"context":{"cacheHit":true,"fileName":"/Users/OliverJAsh/Development/temp/jest-ts-project-references/src/add.ts","logLevel":10,"namespace":"ts-compiler","package":"ts-jest","transformerId":1,"version":"23.10.1"},"message":"getScriptSnapshot(): cache hit","sequence":58,"time":"2018-09-26T16:17:33.535Z"}
{"context":{"diagnosticCodes":[1192],"diagnosticText":"\u001b[96msrc/add.ts\u001b[0m:\u001b[93m1\u001b[0m:\u001b[93m8\u001b[0m - \u001b[91merror\u001b[0m\u001b[90m TS1192: \u001b[0mModule '\"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/add\"' has no default export.\n\n\u001b[30;47m1\u001b[0m import add from 'lodash/add';\n\u001b[30;47m \u001b[0m \u001b[91m       ~~~\u001b[0m\n","logLevel":20,"namespace":"TSError","package":"ts-jest","version":"23.10.1"},"message":"created new TSError","sequence":59,"time":"2018-09-26T16:17:33.537Z"}

Minimal repo :

Full reproduction case

In the full reproduction case I have created, you will see that running tsc -b -f tsconfig.json has no problems, but running jest fails with:

 FAIL  src/__tests__/add.ts
  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/add.ts:1:8 - error TS1192: Module '"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/add"' has no default export.

    1 import add from 'lodash/add';
             ~~~

This failure suggests that the allowSyntheticDefaultImports compiler option, used in tsconfig-tests.json, is not picked up.

huafu commented

Fixed in 23.10.2. This was in fact related to the forced esModuleInterop which has been fixed in 23.10.2.

This was in fact related to the forced esModuleInterop which has been fixed in 23.10.2.

I believe the issue here may be wider than this.

In my testing, no compiler options are respected from the referenced TS project—not just allowSyntheticDefaultImports.

For example: https://github.com/OliverJAsh/jest-ts-project-references/blob/ac25a2d857cae3831d5aff35dd32776f1e47f4a6/src/__tests__/add.ts#L3

Also 23.10.2 does not fix the issue even for the allowSyntheticDefaultImports example given above. Here is the same full reproduction case but upgraded, and you will find the issue still occurs. https://github.com/OliverJAsh/jest-ts-project-references/tree/ts-jest-issue-upgrade

huafu commented

Actually I said it was fixed because I did clone, upgrade and then yarn test which succeeded.

huafu commented

Can you upgrade the minimal repo's master adding an option that makes jest fail while tsc pass?

Be sure to upgrade ts-jest (personally I git clone ..., yarn and then yarn add --dev ts-jest@latest

huafu commented

Arrrrrrgg wrong button, sorry!

Can you upgrade the minimal repo's master

The original repro is on the ts-jest-issue branch.

Be sure to upgrade ts-jest

The upgraded repro is on the ts-jest-issue-upgrade branch. I have checked yarn.lock and it's definitely upgraded.

makes jest fail while tsc pass

tsc does pass and jest fails, as per my original description.

Passes:

$ tsc -b -f tsconfig.json

Fails:

$ jest
 FAIL  src/__tests__/add.ts
  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/add.ts:1:8 - error TS1192: Module '"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/add"' has no default export.

    1 import add from 'lodash/add';
             ~~~
huafu commented

Ok I've tested on master, that might be the reason ;-)

huafu commented

If you have multiple projects, you should have a jest config for each of them as well, and then in the main jest.config.js you'd have a projects field with each of your jest config listed.

Update: But your particular use-case here does not make sense (at least for me). Why would you have, in the same project, different compiler options between the sources and the tests files (except types)? Jest config is where file inclusion/exclusion is made.

Why would you have, in the same project, different options between the sources and the tests files (except types)?

Separating tests from source code are one of the primary use cases for project references (see https://www.typescriptlang.org/docs/handbook/project-references.html#an-example-project).

This separation allows you to have different compiler options, which is useful for specifying different types as in my example. In addition to that, the TypeScript docs themselves specify some other good reasons to do this: https://www.typescriptlang.org/docs/handbook/project-references.html#an-example-project

Previously, this structure was rather awkward to work with if you used a single tsconfig file:

  • It was possible for the implementation files to import the test files
  • It wasn’t possible to build test and src at the same time without having src appear in the output folder name, which you probably don’t want
  • Changing just the internals in the implementation files required typechecking the tests again, even though this wouldn’t ever cause new errors
  • Changing just the tests required typechecking the implementation again, even if nothing changed
  • You could use multiple tsconfig files to solve some of those problems, but new ones would appear:

There’s no built-in up-to-date checking, so you end up always running tsc twice

  • Invoking tsc twice incurs more startup time overhead
  • tsc -w can’t run on multiple config files at once
  • Project references can solve all of these problems and more.

Project references can solve all of these problems and more.

huafu commented

hmmmm... makes sense ok.

I'll look deeper into what are the options here. I'll have to look in their API how they handle this, because we're using the language service so it should work out of the box.

Anyway, until this get fixed, here is how I deal with the problem they exposed:

  • I have a tsconfig.json which has all types, almost no exclude, and noEmit: true.
  • Then I have tsconfig.build.json which extends the tsconfig.json and has noEmit: false, and the correct exclude/include to just build my dist.
huafu commented

@OliverJAsh can you come over ts-jest slack? https://bit.ly/ts-jest-slack

dan-j commented

Any updates on this issue?

I'm not 100% sure if my issue is related, but I have a hunch it is... I've just spent best part of a day trying to get ts-jest to transpile typescript from another module within a monorepo so that coverage is correct.

I think I have jest/ts-jest configured correctly with moduleNameMapper but I get TypeError: ...: Emit skipped. I've debugged down to typescript.js and the output of .getProjectReferences() is undefined.

I have similar problem:

FAIL tests/pages/Project.tsx
Test suite failed to run
TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
tests/pages/Project.tsx:10:27 - error TS2307: Cannot find module '../../src/graphql/projectQuery.gql
import PROJECT_QUERY from "../../src/graphql/projectQuery.gql";

When I run project everything works properly but it when I try to test it fails. I use jest-transform-graphql in the test environment to transpile gql files.

transform: {
  "^.+\\.gql$": "jest-transform-graphql",
}

Any idea how to solve this problem?

Any updates or RIP?

zenby commented

I used this code at jest.config.js to get rid of diagnostics error messages

"jest": {
    "globals": {
      "ts-jest": {
        "diagnostics": {
          "warnOnly": true
        }
      }
    }
  }

This information helped me a lot https://huafu.github.io/ts-jest/user/config/diagnostics

@zenby's solution works, but it's the "nuclear" option. To avoid those "Module 'foo' has no default export." errors, just do this:

globals: {
  "ts-jest": {
    "diagnostics": {          
      "ignoreCodes": "TS1192" 
    }
  }
}

It seems like when resolving import x from 'y', the references:[] in tsconfig is not working.

My test case is removing the built artifacts (i.e. dist or lib and *.tsbuildinfo), and then try to run jest.

The error is Cannot find module 'y'.

tsc -b is working fine.

j commented

@unional I'm having that same issue... did you find a solution?

My solution is to not rely on the diagnostic at all.

I run tsc -b -w in one terminal and jest --watch in another.

You can check out standard-log as an example.

Also, I find that having the diagnostic in the jest actually slows me down.

there are times that I am in the process of refactoring and the type breaks.
For many times I don't care about the type breakage at that moment, I don't want to see if the code work or not.
I can always go back and fix the type.

With diagnostic turned on, I'm force to fix the type on a solution that I don't know if it is correct or not, which would be a waste of time if I will be throwing the code away anyway.

j commented

I got my mono-repo to compile on jest run without having to build files by using moduleNameMapper with typescript project references, etc.

@j how did you do it?

In my case Jest does not even tries to build the project references, it just fails with error:

 FAIL  src/foo.spec.ts
  ● Test suite failed to run

    Cannot find module 'web-modules-core' from 'foo.ts'

    However, Jest was able to find:
        './foo.spec.ts'
        './foo.ts'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'ts', 'tsx'].

    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

    > 1 | export {getConfig} from 'web-modules-core';
        | ^
      2 | 

tsc -b works as expected though.

You have to use moduleNameMapper.
If you are using jest projects and typescript references, then your typescript paths are based on the baseUrl, but the jest paths are based on where the jest.config is located for that project.
So if you have a tsconfig.json with paths defined at the root level and "baseUrl": ".", and a jest config at /packages/example/jest.config.js, then your jest rootdir is at /packages/example and the typescript baseUrl is at /.
So instead of:

{ '^@example/prefix\\-(.*)$': '<rootDir>/packages/$1' }

Your actual path is:

{ '^@example/prefix\\-(.*)$': '<rootDir>/../$1' }

This can be calculated via:

const tsConfigPaths = require('tsconfig-paths')
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { join, dirname, relative } = require('path');

function tsPathsToJestPaths(tsConfigPath) {
  const tsConfigPathsResult = tsConfigPaths.loadConfig(tsConfigPath);
  const paths = tsConfigPathsResult.paths;
  const absolutePaths = Object.keys(paths).reduce((result, moduleName) => {
    result[moduleName] = paths[moduleName].map((path) => {
      const mappedPath = relative(dirname(tsConfigPath), join(dirname(tsConfigPath), tsConfigPathsResult.baseUrl, path))
      return `<rootDir>/${mappedPath}`;
    });
    return result;
  }, {})
  return pathsToModuleNameMapper(absolutePaths)
}

where tsConfigPath is the absolute path to your tsconfig, i.e. resolve(__dirname, "tsconfig.json")

Perhaps ts-jest can automatically do this based on globals.ts-jest.tsConfig

This is not what happened. Modules themselves are just simple Lerna links, that totally can be found by any Node script.

Jest cannot find the module because it does not have build artifacts (JS files that are referred from main of package.json).

It happens because JEST does not initiate build of upstream projects, just like I said.

In my case Jest does not even tries to build the project references, it just fails with error:

 FAIL  src/foo.spec.ts
  ● Test suite failed to run

    Cannot find module 'web-modules-core' from 'foo.ts'

    However, Jest was able to find:
        './foo.spec.ts'
        './foo.ts'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'ts', 'tsx'].

    See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string

    > 1 | export {getConfig} from 'web-modules-core';
        | ^
      2 | 

tsc -b works as expected though.

this might be fixed by #1385, do you have an example repo for your case @kirill-konshin ?

Issue :

Full reproduction case

Expected behavior :

I have three TS projects:

  • tsconfig-src.json
  • tsconfig-tests.json
  • tsconfig.json which references both of the above (using TypeScript's new "project references" feature)

When running jest, it should read compiler options from tsconfig.json.

Because tsconfig.json includes no files for itself but just references other projects, ts-jest should read its compiler options from the project reference that corresponds to any given file.

For example, tsconfig.json references the tsconfig-tests.json project:

{
  "references": [
    {
      "path": "./tsconfig-tests.json"
    }
  ]
}

In turn, tsconfig-tests.json includes all test files:

{
  "include": ["**/__tests__/**/*"]
}

Given this example, I expect any test file matching the tests TS project (tsconfig-tests.json, which includes **/__tests__/**/*) to use compiler options for that TS project.

Actual behaviour

Looking at the logs, I can see tsconfig.json is used. However, compilerOptions is read from tsconfig.json, not tsconfig-tests.json.

I have verified this:

  • When I add compiler options to tsconfig.json, ts-jest uses them.
  • When I add compiler options to tsconfig-tests.json, ts-jest does not use them.

Debug log:

log file content

Minimal repo :

Full reproduction case

In the full reproduction case I have created, you will see that running tsc -b -f tsconfig.json has no problems, but running jest fails with:

 FAIL  src/__tests__/add.ts
  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    src/add.ts:1:8 - error TS1192: Module '"/Users/OliverJAsh/Development/temp/jest-ts-project-references/node_modules/@types/lodash/add"' has no default export.

    1 import add from 'lodash/add';
             ~~~

This failure suggests that the allowSyntheticDefaultImports compiler option, used in tsconfig-tests.json, is not picked up.

I checked out your repo and did some following steps:

  • Upgrade jest, @types/jest, ts-jest, typescript to the latest version
  • Run yarn test

and there is no error anymore. I think your issue is solved with latest dependencies

@ahnpnl Are you using the ts-jest-issue branch? Maybe I didn't make that clear enough in my original post, sorry.

https://github.com/OliverJAsh/jest-ts-project-references/tree/ts-jest-issue

I made a new branch that contains the upgrades you mentioned. The branch still fails:

https://github.com/OliverJAsh/jest-ts-project-references/tree/ts-jest-issue-upgrade

Oh right, I’m sorry. It could be that when cloning the repo to my laptop, I forgot to switch branch. I will take a look again.

Updated: @OliverJAsh indeed i can see the error (even though it's slightly different from what you reported, about esModuleInterop). I need some helps in thinking about the proper solution.

From what I see is your project using typescript project references. When I debug ts-jest source code, I receive the tsconfig input info which contains this
image
So my idea is based on these references, ts-jest will also read tsconfig of these references and combine everything together in the end to create one final configuration to use.

What do you think ?

read tsconfig of these references and combine everything together

That sounds more like the functionality of extends rather than references.

References is a bit more complicated, since the compiler options inside a referenced TS config should only apply to the files in the scope of that TS project.

hmm i'm not experienced with this project reference but your explanation makes some clearance for me. However, I don't know how we can tackle this. Do you have any suggested solutions ?

In general, ts-jest always has a final config which will be used for running tests. This config will affect to the outcome of tests.

References is a bit more complicated, since the compiler options inside a referenced TS config should only apply to the files in the scope of that TS project.

Updated @OliverJAsh I think I found a way to fix the issue. Would you please try:

  • Adjust your tsconfig-base.json to have
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
  • Adjust your jest.config.js to have
globals: {
    'ts-jest': {
      isolatedModules: true,
    }
}

the issue will be fixed by specifying the correct tsconfig for ts-jest to read. In this case, jest.config.js needs to be modified as

globals: {
    'ts-jest': {
        tsConfig: 'tsconfig-tests.json'
    },
},

This will tell ts-jest to use the correct tsconfig. Because by default without specifying tsConfig in ts-jest option, ts-jest will read root tsconfig.json.

Also possibly solved by microsoft/TypeScript#37239

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:

  globals: {
    'ts-jest': {
      isolatedModules: true,
    },
  }

@alexbruno this is not a solution, is a workaround with a drawback: you loose type checking