diff --git a/.eslintrc.js b/.eslintrc.js
index d1ecc65ea7..e00b96a15a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -7,6 +7,9 @@ module.exports = {
ecmaVersion: 2020,
sourceType: 'module',
impliedStrict: true,
+ ecmaFeatures: {
+ jsx: true,
+ },
},
rules: {
'no-console': ['error', { allow: ['warn', 'error', 'log'] }],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af3fcaeb4f..8e31f241c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,5 @@
-# [25.2.1](https://github.com/kulshekhar/ts-jest/compare/25.2.1...25.2.0) (2020-02-21)
+# [25.2.1](https://github.com/kulshekhar/ts-jest/compare/25.2.0...25.2.1) (2020-02-21)
### Bug Fixes
diff --git a/docs/user/config/compilerHost.md b/docs/user/config/compilerHost.md
new file mode 100644
index 0000000000..8bc398c47a
--- /dev/null
+++ b/docs/user/config/compilerHost.md
@@ -0,0 +1,93 @@
+---
+title: Compiler Host option
+---
+
+By default `ts-jest` uses TypeScript `LanguageService` API in the context of a project (yours), with full type-checking and features.
+But TypeScript `Program` can also be used to achieve the same behavior as `LanguageService`.
+That's what the `compilerHost` option (which defaults to `false`) does.
+
+There are 2 types of TypeScript `Program`, one is `Incremental Program` which is only available from TypeScript 3.4
+and the other one is normal `Program`.
+
+By default `ts-jest` uses `Incremental Program` if `compilerHost` is enabled. The priority of using TypeScript APIs in `ts-jest`
+as below:
+- Default TypeScript API is `LanguageService`.
+- `compilerHost` is enabled:
+ - `incremental` is enabled (**default**): use TypeScript `Incremental Program`.
+ - `incremental` is disabled: use TypeScript `Program`.
+- `isolatedModules` is enabled, use TypeScript transpile modules.
+
+Here is how to enable `ts-jest` to compile using TypeScript `Program`
+
+### Example
+
+
+
+```js
+// jest.config.js
+module.exports = {
+ // [...]
+ globals: {
+ 'ts-jest': {
+ compilerHost: true,
+ incremental: false,
+ }
+ }
+};
+```
+
+
+
+```js
+// OR package.json
+{
+ // [...]
+ "jest": {
+ "globals": {
+ "ts-jest": {
+ "compilerHost": true,
+ "incremental": false
+ }
+ }
+ }
+}
+```
+
+
+
+
+Here is how to enable `ts-jest` to compile using TypeScript `IncrementalProgram`
+
+### Example
+
+
+
+```js
+// jest.config.js
+module.exports = {
+ // [...]
+ globals: {
+ 'ts-jest': {
+ compilerHost: true
+ }
+ }
+};
+```
+
+
+
+```js
+// OR package.json
+{
+ // [...]
+ "jest": {
+ "globals": {
+ "ts-jest": {
+ "compilerHost": true
+ }
+ }
+ }
+}
+```
+
+
diff --git a/docs/user/config/index.md b/docs/user/config/index.md
index 7d7eda3bd8..c7ee515358 100644
--- a/docs/user/config/index.md
+++ b/docs/user/config/index.md
@@ -220,6 +220,7 @@ npx ts-jest config:migrate package.json
[compiler]: compiler
[tsConfig]: tsConfig
[isolatedModules]: isolatedModules
+[compilerHost]: compilerHost
[diagnostics]: diagnostics
[babelConfig]: babelConfig
[stringifyContentPathRegex]: stringifyContentPathRegex
diff --git a/e2e/__cases__/compiler-host/main.spec.ts b/e2e/__cases__/compiler-host/main.spec.ts
new file mode 100644
index 0000000000..04bff66dc8
--- /dev/null
+++ b/e2e/__cases__/compiler-host/main.spec.ts
@@ -0,0 +1,6 @@
+import { g } from './main'
+
+it('should pass', () => {
+ const x: string = g(5)
+ expect(x).toBe(5)
+})
diff --git a/e2e/__cases__/compiler-host/main.ts b/e2e/__cases__/compiler-host/main.ts
new file mode 100644
index 0000000000..62b8101c36
--- /dev/null
+++ b/e2e/__cases__/compiler-host/main.ts
@@ -0,0 +1 @@
+export const g = (v: number) => v
diff --git a/e2e/__cases__/composite/foo.spec.ts b/e2e/__cases__/composite/foo.spec.ts
deleted file mode 100644
index 5c772cc97d..0000000000
--- a/e2e/__cases__/composite/foo.spec.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-test('foo', () => {
- expect(true).toBeTruthy();
-});
diff --git a/e2e/__cases__/composite/tsconfig.json b/e2e/__cases__/composite/tsconfig.json
deleted file mode 100644
index 6680bc4fe6..0000000000
--- a/e2e/__cases__/composite/tsconfig.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "compilerOptions": {
- "composite": true,
- "tsBuildInfoFile": ".tsbuildinfo"
- }
-}
diff --git a/e2e/__helpers__/templates.ts b/e2e/__helpers__/templates.ts
index bc0200d235..ff20228f6b 100644
--- a/e2e/__helpers__/templates.ts
+++ b/e2e/__helpers__/templates.ts
@@ -6,5 +6,7 @@ export enum PackageSets {
// invalid
unsupportedVersion = 'with-unsupported-version',
}
-export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7]
-export const allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7]
+export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7],
+ allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7],
+ allPackageSetsWithProgram = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig],
+ allPackageSetsWithoutProgram = [PackageSets.typescript2_7, PackageSets.unsupportedVersion]
diff --git a/e2e/__monorepos__/simple/with-dependency/package.json b/e2e/__monorepos__/simple/with-dependency/package.json
index 1f4d55b21a..d636e4c7bf 100644
--- a/e2e/__monorepos__/simple/with-dependency/package.json
+++ b/e2e/__monorepos__/simple/with-dependency/package.json
@@ -32,7 +32,8 @@
"ts-jest": {
"diagnostics": true,
"tsConfig": "/tsconfig.json",
- "compilerHost": true
+ "compilerHost": true,
+ "incremental": true
}
}
},
diff --git a/e2e/__monorepos__/simple/with-dependency/tsconfig.json b/e2e/__monorepos__/simple/with-dependency/tsconfig.json
index 65f41ccd82..e2a32abfa8 100644
--- a/e2e/__monorepos__/simple/with-dependency/tsconfig.json
+++ b/e2e/__monorepos__/simple/with-dependency/tsconfig.json
@@ -13,8 +13,7 @@
"downlevelIteration": true,
"strict": true,
"moduleResolution": "node",
- "esModuleInterop": true,
- "incremental": true
+ "esModuleInterop": true
},
"include": [
"./src"
diff --git a/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap b/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap
new file mode 100644
index 0000000000..7418daca91
--- /dev/null
+++ b/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap
@@ -0,0 +1,219 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`With compilerHost enabled and incremental disabled should fail using template "with-typescript-2-7" 1`] = `
+ × jest --no-cache
+ ↳ exit code: 1
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ FAIL ./main.spec.ts
+ ● Test suite failed to run
+
+ TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
+
+ at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51)
+
+ Test Suites: 1 failed, 1 total
+ Tests: 0 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental disabled should fail using template "with-unsupported-version" 1`] = `
+ × jest --no-cache
+ ↳ exit code: 1
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions.
+ FAIL ./main.spec.ts
+ ● Test suite failed to run
+
+ TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
+
+ at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51)
+
+ Test Suites: 1 failed, 1 total
+ Tests: 0 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental disabled should pass using template "default" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7-string-config" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental enabled should fail using template "with-typescript-2-7" 1`] = `
+ × jest --no-cache
+ ↳ exit code: 1
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ FAIL ./main.spec.ts
+ ● Test suite failed to run
+
+ TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
+
+ at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51)
+
+ Test Suites: 1 failed, 1 total
+ Tests: 0 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental enabled should fail using template "with-unsupported-version" 1`] = `
+ × jest --no-cache
+ ↳ exit code: 1
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions.
+ FAIL ./main.spec.ts
+ ● Test suite failed to run
+
+ TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
+
+ at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51)
+
+ Test Suites: 1 failed, 1 total
+ Tests: 0 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental enabled should pass using template "default" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7-string-config" 1`] = `
+ √ jest --no-cache
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
+ main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
+
+ 4 const x: string = g(5)
+ ~
+ PASS ./main.spec.ts
+ √ should pass
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
diff --git a/e2e/__tests__/compiler-host.test.ts b/e2e/__tests__/compiler-host.test.ts
new file mode 100644
index 0000000000..21625f4b8d
--- /dev/null
+++ b/e2e/__tests__/compiler-host.test.ts
@@ -0,0 +1,52 @@
+import { allPackageSetsWithProgram, allPackageSetsWithoutProgram } from '../__helpers__/templates'
+import { configureTestCase } from '../__helpers__/test-case'
+
+describe('With compilerHost enabled and incremental disabled', () => {
+ const testCase = configureTestCase('compiler-host', {
+ tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } },
+ noCache: true,
+ })
+
+ testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ // tslint:disable-next-line:no-console
+ console.log = jest.fn()
+ const result = runTest()
+ expect(result.status).toBe(0)
+ expect(result).toMatchSnapshot()
+ })
+ })
+
+ testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ const result = runTest()
+ expect(result.status).toBe(1)
+ expect(result).toMatchSnapshot()
+ })
+ })
+})
+
+describe('With compilerHost enabled and incremental enabled', () => {
+ const testCase = configureTestCase('compiler-host', {
+ tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } },
+ noCache: true,
+ })
+
+ testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ // tslint:disable-next-line:no-console
+ console.log = jest.fn()
+ const result = runTest()
+ expect(result.status).toBe(0)
+ expect(result).toMatchSnapshot()
+ })
+ })
+
+ testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ const result = runTest()
+ expect(result.status).toBe(1)
+ expect(result).toMatchSnapshot()
+ })
+ })
+})
diff --git a/e2e/__tests__/composite.test.ts b/e2e/__tests__/composite.test.ts
deleted file mode 100644
index f2c3bfd874..0000000000
--- a/e2e/__tests__/composite.test.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { PackageSets } from '../__helpers__/templates'
-import { configureTestCase } from '../__helpers__/test-case'
-
-describe('with composite enabled', () => {
- const testCase = configureTestCase('composite')
-
- testCase.runWithTemplates([PackageSets.default], 0, (runTest, { testLabel }) => {
- it(testLabel, () => {
- const result = runTest()
- expect(result.status).toBe(0)
- })
- })
-})
diff --git a/jest.config.js b/jest.config.js
index deb6d6ae4c..9b6a9ccd93 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -11,6 +11,7 @@ module.exports = {
'!/src/**/*.spec.ts',
'!/src/**/*.test.ts',
'!/src/**/__*__/*',
+ '!/src/util/testing.ts',
],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
testEnvironment: 'node',
diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts
index c2e23369a6..483f91e762 100644
--- a/src/__helpers__/fakers.ts
+++ b/src/__helpers__/fakers.ts
@@ -16,6 +16,7 @@ export function tsJestConfig(options?: Partial): TsJestConfig {
return {
compilerHost: false,
emit: false,
+ incremental: false,
isolatedModules: false,
compiler: 'typescript',
transformers: [],
diff --git a/src/__mocks__/tsconfig.json b/src/__mocks__/tsconfig.json
new file mode 100644
index 0000000000..191e175490
--- /dev/null
+++ b/src/__mocks__/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "compilerOptions": {
+ "jsx": "preserve",
+ "outDir": "$$ts-jest$$"
+ }
+}
diff --git a/src/compiler/__snapshots__/language-service.spec.ts.snap b/src/compiler/__snapshots__/language-service.spec.ts.snap
index f12e0f2048..dfe4494771 100644
--- a/src/compiler/__snapshots__/language-service.spec.ts.snap
+++ b/src/compiler/__snapshots__/language-service.spec.ts.snap
@@ -1,38 +1,66 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`language service should compile js file for allowJs true 1`] = `
- ===[ FILE: foo.test.js ]========================================================
+ ===[ FILE: test-allow-js.js ]===================================================
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = 42;
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiZm9vLnRlc3QuanMiLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZSxFQUFFLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZm9vLnRlc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgNDIiXSwidmVyc2lvbiI6M30=
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1hbGxvdy1qcy5qcyIsIm1hcHBpbmdzIjoiOztBQUFBLGtCQUFlLEVBQUUsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWFsbG93LWpzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IDQyIl0sInZlcnNpb24iOjN9
===[ INLINE SOURCE MAPS ]=======================================================
- file: foo.test.js
+ file: test-allow-js.js
mappings: ';;AAAA,kBAAe,EAAE,CAAA'
names: []
sources:
- - foo.test.js
+ - test-allow-js.js
sourcesContent:
- export default 42
version: 3
================================================================================
`;
+exports[`language service should compile tsx file for jsx preserve 1`] = `
+ ===[ FILE: test-jsx-preserve.tsx ]==============================================
+ var App = function () {
+ return <>Test>;
+ };
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNRLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICAgIGNvbnN0IEFwcCA9ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gPD5UZXN0PC8+XG4gICAgICAgIH1cbiAgICAgICJdLCJ2ZXJzaW9uIjozfQ==
+ ===[ INLINE SOURCE MAPS ]=======================================================
+ file: test-jsx-preserve.tsx
+ mappings: 'AACQ,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
+ names: []
+ sources:
+ - test-jsx-preserve.tsx
+ sourcesContent:
+ - |2-
+
+ const App = () => {
+ return <>Test>
+ }
+
+ version: 3
+ ================================================================================
+`;
+
exports[`language service should report diagnostics related to typings with pathRegex config matches file name 1`] = `
"TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
-foo.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."
+test-match-regex-diagnostics.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."
+`;
+
+exports[`language service should throw error when cannot compile 1`] = `
+"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
+This is usually the result of a faulty configuration or import. Make sure there is a \`.js\`, \`.json\` or another executable extension available alongside \`test-cannot-compile.d.ts\`."
`;
exports[`language service should use the cache 3`] = `
- ===[ FILE: src/compiler/language-service.spec.ts ]==============================
+ ===[ FILE: test-cache.ts ]======================================================
console.log("hello");
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL2xhbmd1YWdlLXNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIjxjd2Q+L3NyYy9jb21waWxlci9sYW5ndWFnZS1zZXJ2aWNlLnNwZWMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJoZWxsb1wiKSJdLCJ2ZXJzaW9uIjozfQ==
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1jYWNoZS50cyIsIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbInRlc3QtY2FjaGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJoZWxsb1wiKSJdLCJ2ZXJzaW9uIjozfQ==
===[ INLINE SOURCE MAPS ]=======================================================
- file: /src/compiler/language-service.spec.ts
+ file: test-cache.ts
mappings: 'AAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA'
names: []
sources:
- - /src/compiler/language-service.spec.ts
+ - test-cache.ts
sourcesContent:
- console.log("hello")
version: 3
diff --git a/src/compiler/__snapshots__/program.spec.ts.snap b/src/compiler/__snapshots__/program.spec.ts.snap
index 9dad9a5468..a1d3e3bf83 100644
--- a/src/compiler/__snapshots__/program.spec.ts.snap
+++ b/src/compiler/__snapshots__/program.spec.ts.snap
@@ -36,6 +36,62 @@ exports[`allowJs should compile js file for allowJs true with normal program 1`]
================================================================================
`;
+exports[`cannot compile should throw error with incremental program 1`] = `
+"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
+This is usually the result of a faulty configuration or import. Make sure there is a \`.js\`, \`.json\` or another executable extension available alongside \`test-cannot-compile.d.ts\`."
+`;
+
+exports[`cannot compile should throw error with normal program 1`] = `
+"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
+This is usually the result of a faulty configuration or import. Make sure there is a \`.js\`, \`.json\` or another executable extension available alongside \`test-cannot-compile.d.ts\`."
+`;
+
+exports[`jsx preserve should compile tsx file for jsx preserve with incremental program 1`] = `
+ ===[ FILE: test-jsx-preserve.tsx ]==============================================
+ var App = function () {
+ return <>Test>;
+ };
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNNLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICBjb25zdCBBcHAgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgIH1cbiAgICAiXSwidmVyc2lvbiI6M30=
+ ===[ INLINE SOURCE MAPS ]=======================================================
+ file: test-jsx-preserve.tsx
+ mappings: 'AACM,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
+ names: []
+ sources:
+ - test-jsx-preserve.tsx
+ sourcesContent:
+ - |2-
+
+ const App = () => {
+ return <>Test>
+ }
+
+ version: 3
+ ================================================================================
+`;
+
+exports[`jsx preserve should compile tsx file for jsx preserve with program 1`] = `
+ ===[ FILE: test-jsx-preserve.tsx ]==============================================
+ var App = function () {
+ return <>Test>;
+ };
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNNLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICBjb25zdCBBcHAgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgIH1cbiAgICAiXSwidmVyc2lvbiI6M30=
+ ===[ INLINE SOURCE MAPS ]=======================================================
+ file: test-jsx-preserve.tsx
+ mappings: 'AACM,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
+ names: []
+ sources:
+ - test-jsx-preserve.tsx
+ sourcesContent:
+ - |2-
+
+ const App = () => {
+ return <>Test>
+ }
+
+ version: 3
+ ================================================================================
+`;
+
exports[`typings incremental program should report diagnostics with pathRegex config matches file name 1`] = `"test-typings.ts: Emit skipped"`;
exports[`typings normal program should report diagnostics with pathRegex config matches file name 1`] = `
diff --git a/src/compiler/__snapshots__/transpile-module.spec.ts.snap b/src/compiler/__snapshots__/transpile-module.spec.ts.snap
index de6e87b69b..21783324d1 100644
--- a/src/compiler/__snapshots__/transpile-module.spec.ts.snap
+++ b/src/compiler/__snapshots__/transpile-module.spec.ts.snap
@@ -18,6 +18,29 @@ exports[`transpile module with isolatedModule: true should compile js file for a
================================================================================
`;
+exports[`transpile module with isolatedModule: true should compile tsx file for jsx preserve 1`] = `
+ ===[ FILE: foo.tsx ]============================================================
+ var App = function () {
+ return <>Test>;
+ };
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiZm9vLnRzeCIsIm1hcHBpbmdzIjoiQUFDUSxJQUFNLEdBQUcsR0FBRztJQUNWLE9BQU8sRUFBRSxJQUFJLEdBQUcsQ0FBQTtBQUNsQixDQUFDLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZm9vLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAgICAgY29uc3QgQXBwID0gKCkgPT4ge1xuICAgICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgICAgfVxuICAgICAgIl0sInZlcnNpb24iOjN9
+ ===[ INLINE SOURCE MAPS ]=======================================================
+ file: foo.tsx
+ mappings: 'AACQ,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
+ names: []
+ sources:
+ - foo.tsx
+ sourcesContent:
+ - |2-
+
+ const App = () => {
+ return <>Test>
+ }
+
+ version: 3
+ ================================================================================
+`;
+
exports[`transpile module with isolatedModule: true should compile using transpileModule and not use cache 1`] = `
===[ FILE: src/compiler/transpile-module.spec.ts ]==============================
"use strict";
diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts
index b168c1ee2e..807283bb3a 100644
--- a/src/compiler/instance.ts
+++ b/src/compiler/instance.ts
@@ -175,11 +175,9 @@ export const createCompiler = (configs: ConfigSet): TsCompiler => {
let compileResult: CompileResult
if (!tsJest.isolatedModules) {
// Use language services by default
- if (!tsJest.compilerHost) {
- compileResult = compileUsingLanguageService(configs, logger, memoryCache)
- } else {
- compileResult = compileUsingProgram(configs, logger, memoryCache)
- }
+ compileResult = !tsJest.compilerHost
+ ? compileUsingLanguageService(configs, logger, memoryCache)
+ : compileUsingProgram(configs, logger, memoryCache)
} else {
compileResult = compileUsingTranspileModule(configs, logger)
}
diff --git a/src/compiler/language-service.spec.ts b/src/compiler/language-service.spec.ts
index 87e3bf5e07..be00c492da 100644
--- a/src/compiler/language-service.spec.ts
+++ b/src/compiler/language-service.spec.ts
@@ -19,10 +19,13 @@ describe('language service', () => {
jestConfig: { cache: true, cacheDirectory: tmp },
tsJestConfig: { tsConfig: false },
}),
- source = 'console.log("hello")'
+ source = 'console.log("hello")',
+ fileName = 'test-cache.ts'
+
+ writeFileSync(fileName, source, 'utf8')
logTarget.clear()
- const compiled1 = compiler.compile(source, __filename)
+ const compiled1 = compiler.compile(source, fileName)
expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(`
Array [
@@ -44,7 +47,7 @@ describe('language service', () => {
`)
logTarget.clear()
- const compiled2 = compiler.compile(source, __filename)
+ const compiled2 = compiler.compile(source, fileName)
expect(logTarget.lines).toMatchInlineSnapshot(`
Array [
@@ -53,12 +56,14 @@ describe('language service', () => {
]
`)
- expect(new ProcessedSource(compiled1, __filename)).toMatchSnapshot()
+ expect(new ProcessedSource(compiled1, fileName)).toMatchSnapshot()
expect(compiled2).toBe(compiled1)
+
+ removeSync(fileName)
})
it('should compile js file for allowJs true', () => {
- const fileName = `foo.test.js`,
+ const fileName = `test-allow-js.js`,
compiler = makeCompiler({
tsJestConfig: { tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } },
}),
@@ -72,27 +77,49 @@ describe('language service', () => {
removeSync(fileName)
})
+ it('should compile tsx file for jsx preserve', () => {
+ const fileName = 'test-jsx-preserve.tsx',
+ compiler = makeCompiler({
+ tsJestConfig: { tsConfig: 'src/__mocks__/tsconfig.json' },
+ }),
+ source = `
+ const App = () => {
+ return <>Test>
+ }
+ `
+ writeFileSync(fileName, source, 'utf8')
+ const compiled = compiler.compile(source, fileName)
+
+ expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
+
+ removeSync(fileName)
+ })
+
it('should have correct source maps', () => {
const compiler = makeCompiler({ tsJestConfig: { tsConfig: false } }),
- source = 'const g = (v: number) => v\nconst h: number = g(5)'
+ source = 'const gsm = (v: number) => v\nconst h: number = gsm(5)',
+ fileName = 'test-source-map.ts'
+ writeFileSync(fileName, source, 'utf8')
- const compiled = compiler.compile(source, 'foo.ts')
+ const compiled = compiler.compile(source, fileName)
- expect(new ProcessedSource(compiled, 'foo.ts').outputSourceMaps).toMatchObject({
- file: 'foo.ts',
- sources: ['foo.ts'],
+ expect(new ProcessedSource(compiled, fileName).outputSourceMaps).toMatchObject({
+ file: fileName,
+ sources: [fileName],
sourcesContent: [source],
})
+
+ removeSync(fileName)
})
it('should report diagnostics related to typings with pathRegex config matches file name', () => {
- const fileName = 'foo.ts',
+ const fileName = 'test-match-regex-diagnostics.ts',
source = `
const g = (v: number) => v
const x: string = g(5)
`,
compiler = makeCompiler({
- tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: 'foo.ts' } },
+ tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: fileName } },
})
writeFileSync(fileName, source, 'utf8')
@@ -102,7 +129,7 @@ const x: string = g(5)
})
it('should not report diagnostics related to typings with pathRegex config does not match file name', () => {
- const fileName = 'foo.ts',
+ const fileName = 'test-non-match-regex-diagnostics.ts',
source = `
const f = (v: number) => v
const t: string = f(5)
@@ -116,4 +143,21 @@ const t: string = f(5)
removeSync(fileName)
})
+
+ it('should throw error when cannot compile', () => {
+ const fileName = 'test-cannot-compile.d.ts',
+ source = `
+ interface Foo {
+ a: string
+ }
+ `,
+ compiler = makeCompiler({
+ tsJestConfig: { tsConfig: false },
+ })
+ writeFileSync(fileName, source, 'utf8')
+
+ expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
+
+ removeSync(fileName)
+ })
})
diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts
index 2f2261519d..2ba934855d 100644
--- a/src/compiler/language-service.ts
+++ b/src/compiler/language-service.ts
@@ -124,7 +124,6 @@ export const compileUsingLanguageService = (
previousProgram = programAfter
// Throw an error when requiring `.d.ts` files.
- /* istanbul ignore next (this should never happen but is kept for security) */
if (!output.outputFiles.length) {
throw new TypeError(
interpolate(Errors.UnableToRequireDefinitionFile, {
diff --git a/src/compiler/program.spec.ts b/src/compiler/program.spec.ts
index 91b8e6c988..02c2eef230 100644
--- a/src/compiler/program.spec.ts
+++ b/src/compiler/program.spec.ts
@@ -33,7 +33,7 @@ const t: string = f(5)
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: false },
+ incremental: false,
diagnostics: { pathRegex: fileName },
},
})
@@ -45,7 +45,7 @@ const t: string = f(5)
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: false },
+ incremental: false,
diagnostics: { pathRegex: 'foo.ts' },
},
})
@@ -63,7 +63,7 @@ const t: string = f(5)
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: true },
+ incremental: true,
diagnostics: { pathRegex: 'typings-error.ts' },
},
})
@@ -75,7 +75,7 @@ const t: string = f(5)
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: true },
+ incremental: true,
diagnostics: { pathRegex: 'foo.ts' },
},
})
@@ -105,7 +105,7 @@ describe('source-maps', () => {
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: false },
+ incremental: false,
},
})
@@ -122,7 +122,7 @@ describe('source-maps', () => {
const compiler = makeCompiler({
tsJestConfig: {
...baseTsJestConfig,
- tsConfig: { incremental: true },
+ incremental: true,
},
})
@@ -137,8 +137,7 @@ describe('source-maps', () => {
})
describe('cache', () => {
- const tmp = tempDir('compiler'),
- fileName = 'test-cache.ts',
+ const fileName = 'test-cache.ts',
source = 'console.log("hello")'
beforeAll(() => {
@@ -150,13 +149,14 @@ describe('cache', () => {
})
it('should use the cache with normal program', () => {
- const compiler = makeCompiler({
- jestConfig: { cache: true, cacheDirectory: tmp },
- tsJestConfig: {
- ...baseTsJestConfig,
- tsConfig: { incremental: false },
- },
- })
+ const tmp = tempDir('program-compiler'),
+ compiler = makeCompiler({
+ jestConfig: { cache: true, cacheDirectory: tmp },
+ tsJestConfig: {
+ ...baseTsJestConfig,
+ incremental: false,
+ },
+ })
logTarget.clear()
const compiled1 = compiler.compile(source, fileName)
@@ -187,14 +187,15 @@ describe('cache', () => {
expect(compiled2).toBe(compiled1)
})
- it('should use the cache with normal program', () => {
- const compiler = makeCompiler({
- jestConfig: { cache: true, cacheDirectory: tmp },
- tsJestConfig: {
- ...baseTsJestConfig,
- tsConfig: { incremental: true },
- },
- })
+ it('should use the cache with incremental program', () => {
+ const tmp = tempDir('incremental-program-compiler'),
+ compiler = makeCompiler({
+ jestConfig: { cache: true, cacheDirectory: tmp },
+ tsJestConfig: {
+ ...baseTsJestConfig,
+ incremental: true,
+ },
+ })
logTarget.clear()
const compiled1 = compiler.compile(source, fileName)
@@ -202,7 +203,7 @@ describe('cache', () => {
Array [
"[level:20] readThrough(): cache miss
",
- "[level:20] updateMemoryCache() for program
+ "[level:20] updateMemoryCache() for incremental program
",
"[level:20] visitSourceFileNode(): hoisting
",
@@ -228,7 +229,8 @@ Array [
describe('allowJs', () => {
const fileName = 'test-allowJs.test.js',
- source = 'export default 42'
+ source = 'export default 42',
+ tsConfig = { allowJs: true, outDir: '$$ts-jest$$' }
beforeAll(() => {
writeFileSync(fileName, source, 'utf8')
@@ -240,7 +242,7 @@ describe('allowJs', () => {
it('should compile js file for allowJs true with normal program', () => {
const compiler = makeCompiler({
- tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$', incremental: false } },
+ tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig },
})
const compiled = compiler.compile(source, fileName)
@@ -250,7 +252,7 @@ describe('allowJs', () => {
it('should compile js file for allowJs true with incremental program', () => {
const compiler = makeCompiler({
- tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$', incremental: true } },
+ tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig },
})
const compiled = compiler.compile(source, fileName)
@@ -258,3 +260,74 @@ describe('allowJs', () => {
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
})
})
+
+describe('jsx preserve', () => {
+ const fileName = 'test-jsx-preserve.tsx',
+ source = `
+ const App = () => {
+ return <>Test>
+ }
+ `,
+ tsConfig = 'src/__mocks__/tsconfig.json'
+
+ beforeAll(() => {
+ writeFileSync(fileName, source, 'utf8')
+ })
+
+ afterAll(() => {
+ removeSync(fileName)
+ })
+
+ it('should compile tsx file for jsx preserve with program', () => {
+ const compiler = makeCompiler({
+ tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig },
+ })
+
+ const compiled = compiler.compile(source, fileName)
+
+ expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
+ })
+
+ it('should compile tsx file for jsx preserve with incremental program', () => {
+ const compiler = makeCompiler({
+ tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig },
+ })
+
+ const compiled = compiler.compile(source, fileName)
+
+ expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
+ })
+})
+
+describe('cannot compile', () => {
+ const fileName = 'test-cannot-compile.d.ts',
+ source = `
+ interface Foo {
+ a: string
+ }
+ `
+
+ beforeAll(() => {
+ writeFileSync(fileName, source, 'utf8')
+ })
+
+ afterAll(() => {
+ removeSync(fileName)
+ })
+
+ it('should throw error with normal program', () => {
+ const compiler = makeCompiler({
+ tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig: false },
+ })
+
+ expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
+ })
+
+ it('should throw error with incremental program', () => {
+ const compiler = makeCompiler({
+ tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig: false },
+ })
+
+ expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
+ })
+})
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index b7822a9c33..4cf8a1d079 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -15,7 +15,8 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
const ts = configs.compilerModule,
cwd = configs.cwd,
- { options, fileNames, projectReferences, errors } = configs.typescript
+ { options, fileNames, projectReferences, errors } = configs.typescript,
+ incremental = configs.tsJest.incremental
const compilerHostTraceCtx = {
namespace: 'ts:compilerHost',
call: null,
@@ -36,8 +37,9 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
}
let builderProgram: _ts.EmitAndSemanticDiagnosticsBuilderProgram, program: _ts.Program, host: _ts.CompilerHost
- // Fallback for older TypeScript releases without incremental API.
- if (options.incremental) {
+ if (incremental) {
+ // TODO: Find a way to trigger typescript to build project when there are project references.
+ // At the moment this Incremental Program doesn't work with project references
host = ts.createIncrementalCompilerHost(options, sys)
builderProgram = ts.createIncrementalProgram({
rootNames: fileNames.slice(),
@@ -48,6 +50,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
})
program = builderProgram.getProgram()
} else {
+ // Fallback for older TypeScript releases without incremental API.
host = {
...sys,
getSourceFile: (fileName, languageVersion) => {
@@ -71,7 +74,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
// Read and cache custom transformers.
const customTransformers = configs.tsCustomTransformers,
updateMemoryCache = (contents: string, normalizedFileName: string): void => {
- logger.debug({ normalizedFileName }, `updateMemoryCache() for program`)
+ logger.debug({ normalizedFileName }, `updateMemoryCache() for ${incremental ? 'incremental program' : 'program'}`)
const fileVersion = memoryCache.versions.get(normalizedFileName) ?? 0,
isFileInCache = fileVersion !== 0
@@ -84,7 +87,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
memoryCache.versions.set(normalizedFileName, fileVersion + 1)
memoryCache.contents.set(normalizedFileName, contents)
}
- const sourceFile = options.incremental
+ const sourceFile = incremental
? builderProgram.getSourceFile(normalizedFileName)
: program.getSourceFile(normalizedFileName)
// Update program when file changes.
@@ -100,7 +103,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
configFileParsingDiagnostics: errors,
projectReferences,
}
- if (options.incremental) {
+ if (incremental) {
builderProgram = ts.createIncrementalProgram(programOptions)
program = builderProgram.getProgram()
} else {
@@ -114,13 +117,13 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
output: [string, string] = ['', '']
// Must set memory cache before attempting to read file.
updateMemoryCache(code, normalizedFileName)
- const sourceFile = options.incremental
+ const sourceFile = incremental
? builderProgram.getSourceFile(normalizedFileName)
: program.getSourceFile(normalizedFileName)
if (!sourceFile) throw new TypeError(`Unable to read file: ${fileName}`)
- const result: _ts.EmitResult = options.incremental
+ const result: _ts.EmitResult = incremental
? builderProgram.emit(
sourceFile,
(path, file, _writeByteOrderMark) => {
@@ -142,7 +145,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
if (configs.shouldReportDiagnostic(normalizedFileName)) {
logger.debug(
{ normalizedFileName },
- `getOutput(): computing diagnostics for ${options.incremental ? 'incremental program' : 'program'}`,
+ `getOutput(): computing diagnostics for ${incremental ? 'incremental program' : 'program'}`,
)
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile).slice()
// will raise or just warn diagnostics depending on config
@@ -165,7 +168,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
}),
)
}
- if (configs.tsJest.emit && options.incremental) {
+ if (configs.tsJest.emit && incremental) {
process.on('exit', () => {
// Emits `.tsbuildinfo` to filesystem.
// @ts-ignore
diff --git a/src/compiler/transpile-module.spec.ts b/src/compiler/transpile-module.spec.ts
index 5c1ed108b6..dbaaf33e92 100644
--- a/src/compiler/transpile-module.spec.ts
+++ b/src/compiler/transpile-module.spec.ts
@@ -54,6 +54,25 @@ describe('transpile module with isolatedModule: true', () => {
removeSync(fileName)
})
+ it('should compile tsx file for jsx preserve', () => {
+ const fileName = `foo.tsx`,
+ compiler = makeCompiler({
+ tsJestConfig: { ...baseTsJestConfig, tsConfig: 'src/__mocks__/tsconfig.json' },
+ }),
+ source = `
+ const App = () => {
+ return <>Test>
+ }
+ `
+
+ writeFileSync(fileName, source, 'utf8')
+ const compiled = compiler.compile(source, fileName)
+
+ expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
+
+ removeSync(fileName)
+ })
+
it('should have correct source maps', () => {
const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }),
source = 'const f = (v: number) => v\nconst t: number = f(5)'
diff --git a/src/config/__snapshots__/config-set.spec.ts.snap b/src/config/__snapshots__/config-set.spec.ts.snap
index bb58b30cc6..fb75af528a 100644
--- a/src/config/__snapshots__/config-set.spec.ts.snap
+++ b/src/config/__snapshots__/config-set.spec.ts.snap
@@ -53,6 +53,7 @@ Object {
"throws": true,
},
"emit": false,
+ "incremental": true,
"isolatedModules": false,
"packageJson": Object {
"kind": "file",
@@ -143,6 +144,7 @@ Object {
"throws": true,
},
"emit": false,
+ "incremental": true,
"isolatedModules": false,
"packageJson": Object {
"kind": "file",
diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts
index 3683f768c3..d2641e6095 100644
--- a/src/config/config-set.spec.ts
+++ b/src/config/config-set.spec.ts
@@ -966,7 +966,7 @@ describe('cacheKey', () => {
cs.jsonValue.value = val
// digest is mocked in src/__mocks__/index.ts
expect(cs.cacheKey).toMatchInlineSnapshot(
- `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"compilerHost\\":false,\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"emit\\":false,\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"`,
+ `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"compilerHost\\":false,\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"emit\\":false,\\"incremental\\":true,\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":[]},\\"tsconfig\\":{\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1}}"`,
)
})
}) // cacheKey
diff --git a/src/config/config-set.ts b/src/config/config-set.ts
index c39d5bea61..de04735210 100644
--- a/src/config/config-set.ts
+++ b/src/config/config-set.ts
@@ -266,6 +266,7 @@ export class ConfigSet {
const res: TsJestConfig = {
tsConfig,
compilerHost: options.compilerHost ?? false,
+ incremental: options.incremental ?? true,
emit: options.emit ?? false,
packageJson,
babelConfig,
diff --git a/src/ts-jest-transformer.spec.ts b/src/ts-jest-transformer.spec.ts
index c0cc3e4209..1e9aef0f06 100644
--- a/src/ts-jest-transformer.spec.ts
+++ b/src/ts-jest-transformer.spec.ts
@@ -8,7 +8,15 @@ import { ConfigSet } from './config/config-set'
import { TsJestTransformer } from './ts-jest-transformer'
describe('configFor', () => {
- it('should return the same config-set for same values', () => {
+ it('should return the same config-set for same values with jest config string is not in configSetsIndex', () => {
+ const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
+ const str = stringify(obj1)
+ const cs3 = new TsJestTransformer().configsFor(str)
+ expect(cs3.cwd).toBe(`${sep}foo`)
+ expect(cs3.rootDir).toBe(`${sep}bar`)
+ })
+
+ it('should return the same config-set for same values with jest config string in configSetsIndex', () => {
const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
const obj2 = { ...obj1 }
const str = stringify(obj1)
@@ -70,12 +78,12 @@ describe('process', () => {
it('should process ts input without babel', () => {
expect(process()).toBe(`ts:${INPUT}`)
expect(config.shouldStringifyContent.mock.calls).toMatchInlineSnapshot(`
-Array [
- Array [
- "/foo/bar.ts",
- ],
-]
-`)
+ Array [
+ Array [
+ "/foo/bar.ts",
+ ],
+ ]
+ `)
expect(config.tsCompiler.compile.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
@@ -194,6 +202,11 @@ Array [
`)
})
+ it('should return empty string when trying to process definition file types', () => {
+ args[1] = '/foo/bar.d.ts'
+ expect(process()).toBe('')
+ })
+
it('should warn when trying to process unknown file types', () => {
args[1] = '/foo/bar.jest'
const logs = logTargetMock()
diff --git a/src/ts-jest-transformer.ts b/src/ts-jest-transformer.ts
index 17b5658ae0..69796476fd 100644
--- a/src/ts-jest-transformer.ts
+++ b/src/ts-jest-transformer.ts
@@ -62,7 +62,7 @@ export class TsJestTransformer implements Transformer {
return `[object TsJestTransformer<#${this.id}>]`
}
- configsFor(jestConfig: Config.ProjectConfig | string) {
+ configsFor(jestConfig: Config.ProjectConfig | string): ConfigSet {
let csi: ConfigSetIndexItem | undefined
let jestConfigObj: Config.ProjectConfig
if (typeof jestConfig === 'string') {
diff --git a/src/types.ts b/src/types.ts
index 1b5b8e75f2..831130d3ef 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -44,6 +44,13 @@ export interface TsJestGlobalOptions {
*/
compilerHost?: boolean
+ /**
+ * Use TypeScript's Incremental Program. This option only works when `compilerHost` is `true`
+ * TODO: Remove this flag when we can make project references working with our Incremental Program
+ * @default false
+ */
+ incremental?: boolean
+
/**
* Emit compiled files into `.ts-jest` directory
*
@@ -142,6 +149,7 @@ export interface TsJestConfig {
packageJson: TsJestConfig$packageJson
isolatedModules: boolean
compilerHost: boolean
+ incremental: boolean // TODO: Remove this flag when we can make project references working with our Incremental Program
emit: boolean
compiler: string
diagnostics: TsJestConfig$diagnostics