Skip to content

Commit 5a69bce

Browse files
authoredMar 7, 2020
feat(config): add incremental option (#1418)
1 parent a0ddca7 commit 5a69bce

32 files changed

+732
-102
lines changed
 

‎.eslintrc.js

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ module.exports = {
77
ecmaVersion: 2020,
88
sourceType: 'module',
99
impliedStrict: true,
10+
ecmaFeatures: {
11+
jsx: true,
12+
},
1013
},
1114
rules: {
1215
'no-console': ['error', { allow: ['warn', 'error', 'log'] }],

‎CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<a name="25.2.1"></a>
2-
# [25.2.1](https://github.com/kulshekhar/ts-jest/compare/25.2.1...25.2.0) (2020-02-21)
2+
# [25.2.1](https://github.com/kulshekhar/ts-jest/compare/25.2.0...25.2.1) (2020-02-21)
33

44

55
### Bug Fixes

‎docs/user/config/compilerHost.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
title: Compiler Host option
3+
---
4+
5+
By default `ts-jest` uses TypeScript `LanguageService` API in the context of a project (yours), with full type-checking and features.
6+
But TypeScript `Program` can also be used to achieve the same behavior as `LanguageService`.
7+
That's what the `compilerHost` option (which defaults to `false`) does.
8+
9+
There are 2 types of TypeScript `Program`, one is `Incremental Program` which is only available from TypeScript 3.4
10+
and the other one is normal `Program`.
11+
12+
By default `ts-jest` uses `Incremental Program` if `compilerHost` is enabled. The priority of using TypeScript APIs in `ts-jest`
13+
as below:
14+
- Default TypeScript API is `LanguageService`.
15+
- `compilerHost` is enabled:
16+
- `incremental` is enabled (**default**): use TypeScript `Incremental Program`.
17+
- `incremental` is disabled: use TypeScript `Program`.
18+
- `isolatedModules` is enabled, use TypeScript transpile modules.
19+
20+
Here is how to enable `ts-jest` to compile using TypeScript `Program`
21+
22+
### Example
23+
24+
<div class="row"><div class="col-md-6" markdown="block">
25+
26+
```js
27+
// jest.config.js
28+
module.exports = {
29+
// [...]
30+
globals: {
31+
'ts-jest': {
32+
compilerHost: true,
33+
incremental: false,
34+
}
35+
}
36+
};
37+
```
38+
39+
</div><div class="col-md-6" markdown="block">
40+
41+
```js
42+
// OR package.json
43+
{
44+
// [...]
45+
"jest": {
46+
"globals": {
47+
"ts-jest": {
48+
"compilerHost": true,
49+
"incremental": false
50+
}
51+
}
52+
}
53+
}
54+
```
55+
56+
</div></div>
57+
58+
59+
Here is how to enable `ts-jest` to compile using TypeScript `IncrementalProgram`
60+
61+
### Example
62+
63+
<div class="row"><div class="col-md-6" markdown="block">
64+
65+
```js
66+
// jest.config.js
67+
module.exports = {
68+
// [...]
69+
globals: {
70+
'ts-jest': {
71+
compilerHost: true
72+
}
73+
}
74+
};
75+
```
76+
77+
</div><div class="col-md-6" markdown="block">
78+
79+
```js
80+
// OR package.json
81+
{
82+
// [...]
83+
"jest": {
84+
"globals": {
85+
"ts-jest": {
86+
"compilerHost": true
87+
}
88+
}
89+
}
90+
}
91+
```
92+
93+
</div></div>

‎docs/user/config/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ npx ts-jest config:migrate package.json
220220
[compiler]: compiler
221221
[tsConfig]: tsConfig
222222
[isolatedModules]: isolatedModules
223+
[compilerHost]: compilerHost
223224
[diagnostics]: diagnostics
224225
[babelConfig]: babelConfig
225226
[stringifyContentPathRegex]: stringifyContentPathRegex
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { g } from './main'
2+
3+
it('should pass', () => {
4+
const x: string = g(5)
5+
expect(x).toBe(5)
6+
})

‎e2e/__cases__/compiler-host/main.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const g = (v: number) => v

‎e2e/__cases__/composite/foo.spec.ts

-3
This file was deleted.

‎e2e/__cases__/composite/tsconfig.json

-6
This file was deleted.

‎e2e/__helpers__/templates.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ export enum PackageSets {
66
// invalid
77
unsupportedVersion = 'with-unsupported-version',
88
}
9-
export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7]
10-
export const allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7]
9+
export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7],
10+
allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7],
11+
allPackageSetsWithProgram = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig],
12+
allPackageSetsWithoutProgram = [PackageSets.typescript2_7, PackageSets.unsupportedVersion]

‎e2e/__monorepos__/simple/with-dependency/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"ts-jest": {
3333
"diagnostics": true,
3434
"tsConfig": "<rootDir>/tsconfig.json",
35-
"compilerHost": true
35+
"compilerHost": true,
36+
"incremental": true
3637
}
3738
}
3839
},

‎e2e/__monorepos__/simple/with-dependency/tsconfig.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
"downlevelIteration": true,
1414
"strict": true,
1515
"moduleResolution": "node",
16-
"esModuleInterop": true,
17-
"incremental": true
16+
"esModuleInterop": true
1817
},
1918
"include": [
2019
"./src"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`With compilerHost enabled and incremental disabled should fail using template "with-typescript-2-7" 1`] = `
4+
× jest --no-cache
5+
↳ exit code: 1
6+
===[ STDOUT ]===================================================================
7+
8+
===[ STDERR ]===================================================================
9+
FAIL ./main.spec.ts
10+
● Test suite failed to run
11+
12+
TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
13+
14+
at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51)
15+
16+
Test Suites: 1 failed, 1 total
17+
Tests: 0 total
18+
Snapshots: 0 total
19+
Time: XXs
20+
Ran all test suites.
21+
================================================================================
22+
`;
23+
24+
exports[`With compilerHost enabled and incremental disabled should fail using template "with-unsupported-version" 1`] = `
25+
× jest --no-cache
26+
↳ exit code: 1
27+
===[ STDOUT ]===================================================================
28+
29+
===[ STDERR ]===================================================================
30+
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.
31+
FAIL ./main.spec.ts
32+
● Test suite failed to run
33+
34+
TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
35+
36+
at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51)
37+
38+
Test Suites: 1 failed, 1 total
39+
Tests: 0 total
40+
Snapshots: 0 total
41+
Time: XXs
42+
Ran all test suites.
43+
================================================================================
44+
`;
45+
46+
exports[`With compilerHost enabled and incremental disabled should pass using template "default" 1`] = `
47+
√ jest --no-cache
48+
↳ exit code: 0
49+
===[ STDOUT ]===================================================================
50+
51+
===[ STDERR ]===================================================================
52+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
53+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
54+
55+
4 const x: string = g(5)
56+
~
57+
PASS ./main.spec.ts
58+
√ should pass
59+
60+
Test Suites: 1 passed, 1 total
61+
Tests: 1 passed, 1 total
62+
Snapshots: 0 total
63+
Time: XXs
64+
Ran all test suites.
65+
================================================================================
66+
`;
67+
68+
exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7" 1`] = `
69+
√ jest --no-cache
70+
↳ exit code: 0
71+
===[ STDOUT ]===================================================================
72+
73+
===[ STDERR ]===================================================================
74+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
75+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
76+
77+
4 const x: string = g(5)
78+
~
79+
PASS ./main.spec.ts
80+
√ should pass
81+
82+
Test Suites: 1 passed, 1 total
83+
Tests: 1 passed, 1 total
84+
Snapshots: 0 total
85+
Time: XXs
86+
Ran all test suites.
87+
================================================================================
88+
`;
89+
90+
exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7-string-config" 1`] = `
91+
√ jest --no-cache
92+
↳ exit code: 0
93+
===[ STDOUT ]===================================================================
94+
95+
===[ STDERR ]===================================================================
96+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
97+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
98+
99+
4 const x: string = g(5)
100+
~
101+
PASS ./main.spec.ts
102+
√ should pass
103+
104+
Test Suites: 1 passed, 1 total
105+
Tests: 1 passed, 1 total
106+
Snapshots: 0 total
107+
Time: XXs
108+
Ran all test suites.
109+
================================================================================
110+
`;
111+
112+
exports[`With compilerHost enabled and incremental enabled should fail using template "with-typescript-2-7" 1`] = `
113+
× jest --no-cache
114+
↳ exit code: 1
115+
===[ STDOUT ]===================================================================
116+
117+
===[ STDERR ]===================================================================
118+
FAIL ./main.spec.ts
119+
● Test suite failed to run
120+
121+
TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
122+
123+
at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51)
124+
125+
Test Suites: 1 failed, 1 total
126+
Tests: 0 total
127+
Snapshots: 0 total
128+
Time: XXs
129+
Ran all test suites.
130+
================================================================================
131+
`;
132+
133+
exports[`With compilerHost enabled and incremental enabled should fail using template "with-unsupported-version" 1`] = `
134+
× jest --no-cache
135+
↳ exit code: 1
136+
===[ STDOUT ]===================================================================
137+
138+
===[ STDERR ]===================================================================
139+
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.
140+
FAIL ./main.spec.ts
141+
● Test suite failed to run
142+
143+
TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined
144+
145+
at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51)
146+
147+
Test Suites: 1 failed, 1 total
148+
Tests: 0 total
149+
Snapshots: 0 total
150+
Time: XXs
151+
Ran all test suites.
152+
================================================================================
153+
`;
154+
155+
exports[`With compilerHost enabled and incremental enabled should pass using template "default" 1`] = `
156+
√ jest --no-cache
157+
↳ exit code: 0
158+
===[ STDOUT ]===================================================================
159+
160+
===[ STDERR ]===================================================================
161+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
162+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
163+
164+
4 const x: string = g(5)
165+
~
166+
PASS ./main.spec.ts
167+
√ should pass
168+
169+
Test Suites: 1 passed, 1 total
170+
Tests: 1 passed, 1 total
171+
Snapshots: 0 total
172+
Time: XXs
173+
Ran all test suites.
174+
================================================================================
175+
`;
176+
177+
exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7" 1`] = `
178+
√ jest --no-cache
179+
↳ exit code: 0
180+
===[ STDOUT ]===================================================================
181+
182+
===[ STDERR ]===================================================================
183+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
184+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
185+
186+
4 const x: string = g(5)
187+
~
188+
PASS ./main.spec.ts
189+
√ should pass
190+
191+
Test Suites: 1 passed, 1 total
192+
Tests: 1 passed, 1 total
193+
Snapshots: 0 total
194+
Time: XXs
195+
Ran all test suites.
196+
================================================================================
197+
`;
198+
199+
exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7-string-config" 1`] = `
200+
√ jest --no-cache
201+
↳ exit code: 0
202+
===[ STDOUT ]===================================================================
203+
204+
===[ STDERR ]===================================================================
205+
ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
206+
main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'.
207+
208+
4 const x: string = g(5)
209+
~
210+
PASS ./main.spec.ts
211+
√ should pass
212+
213+
Test Suites: 1 passed, 1 total
214+
Tests: 1 passed, 1 total
215+
Snapshots: 0 total
216+
Time: XXs
217+
Ran all test suites.
218+
================================================================================
219+
`;

‎e2e/__tests__/compiler-host.test.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { allPackageSetsWithProgram, allPackageSetsWithoutProgram } from '../__helpers__/templates'
2+
import { configureTestCase } from '../__helpers__/test-case'
3+
4+
describe('With compilerHost enabled and incremental disabled', () => {
5+
const testCase = configureTestCase('compiler-host', {
6+
tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } },
7+
noCache: true,
8+
})
9+
10+
testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => {
11+
it(testLabel, () => {
12+
// tslint:disable-next-line:no-console
13+
console.log = jest.fn()
14+
const result = runTest()
15+
expect(result.status).toBe(0)
16+
expect(result).toMatchSnapshot()
17+
})
18+
})
19+
20+
testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => {
21+
it(testLabel, () => {
22+
const result = runTest()
23+
expect(result.status).toBe(1)
24+
expect(result).toMatchSnapshot()
25+
})
26+
})
27+
})
28+
29+
describe('With compilerHost enabled and incremental enabled', () => {
30+
const testCase = configureTestCase('compiler-host', {
31+
tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } },
32+
noCache: true,
33+
})
34+
35+
testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => {
36+
it(testLabel, () => {
37+
// tslint:disable-next-line:no-console
38+
console.log = jest.fn()
39+
const result = runTest()
40+
expect(result.status).toBe(0)
41+
expect(result).toMatchSnapshot()
42+
})
43+
})
44+
45+
testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => {
46+
it(testLabel, () => {
47+
const result = runTest()
48+
expect(result.status).toBe(1)
49+
expect(result).toMatchSnapshot()
50+
})
51+
})
52+
})

‎e2e/__tests__/composite.test.ts

-13
This file was deleted.

‎jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
'!<rootDir>/src/**/*.spec.ts',
1212
'!<rootDir>/src/**/*.test.ts',
1313
'!<rootDir>/src/**/__*__/*',
14+
'!<rootDir>/src/util/testing.ts',
1415
],
1516
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
1617
testEnvironment: 'node',

‎src/__helpers__/fakers.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export function tsJestConfig(options?: Partial<TsJestConfig>): TsJestConfig {
1616
return {
1717
compilerHost: false,
1818
emit: false,
19+
incremental: false,
1920
isolatedModules: false,
2021
compiler: 'typescript',
2122
transformers: [],

‎src/__mocks__/tsconfig.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"compilerOptions": {
3+
"jsx": "preserve",
4+
"outDir": "$$ts-jest$$"
5+
}
6+
}

‎src/compiler/__snapshots__/language-service.spec.ts.snap

+37-9
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,66 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`language service should compile js file for allowJs true 1`] = `
4-
===[ FILE: foo.test.js ]========================================================
4+
===[ FILE: test-allow-js.js ]===================================================
55
"use strict";
66
Object.defineProperty(exports, "__esModule", { value: true });
77
exports.default = 42;
8-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiZm9vLnRlc3QuanMiLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZSxFQUFFLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZm9vLnRlc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgNDIiXSwidmVyc2lvbiI6M30=
8+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1hbGxvdy1qcy5qcyIsIm1hcHBpbmdzIjoiOztBQUFBLGtCQUFlLEVBQUUsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWFsbG93LWpzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IDQyIl0sInZlcnNpb24iOjN9
99
===[ INLINE SOURCE MAPS ]=======================================================
10-
file: foo.test.js
10+
file: test-allow-js.js
1111
mappings: ';;AAAA,kBAAe,EAAE,CAAA'
1212
names: []
1313
sources:
14-
- foo.test.js
14+
- test-allow-js.js
1515
sourcesContent:
1616
- export default 42
1717
version: 3
1818
================================================================================
1919
`;
2020

21+
exports[`language service should compile tsx file for jsx preserve 1`] = `
22+
===[ FILE: test-jsx-preserve.tsx ]==============================================
23+
var App = function () {
24+
return <>Test</>;
25+
};
26+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNRLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICAgIGNvbnN0IEFwcCA9ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gPD5UZXN0PC8+XG4gICAgICAgIH1cbiAgICAgICJdLCJ2ZXJzaW9uIjozfQ==
27+
===[ INLINE SOURCE MAPS ]=======================================================
28+
file: test-jsx-preserve.tsx
29+
mappings: 'AACQ,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
30+
names: []
31+
sources:
32+
- test-jsx-preserve.tsx
33+
sourcesContent:
34+
- |2-
35+
36+
const App = () => {
37+
return <>Test</>
38+
}
39+
40+
version: 3
41+
================================================================================
42+
`;
43+
2144
exports[`language service should report diagnostics related to typings with pathRegex config matches file name 1`] = `
2245
"TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option):
23-
foo.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."
46+
test-match-regex-diagnostics.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."
47+
`;
48+
49+
exports[`language service should throw error when cannot compile 1`] = `
50+
"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
51+
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\`."
2452
`;
2553

2654
exports[`language service should use the cache 3`] = `
27-
===[ FILE: src/compiler/language-service.spec.ts ]==============================
55+
===[ FILE: test-cache.ts ]======================================================
2856
console.log("hello");
29-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiPGN3ZD4vc3JjL2NvbXBpbGVyL2xhbmd1YWdlLXNlcnZpY2Uuc3BlYy50cyIsIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIjxjd2Q+L3NyYy9jb21waWxlci9sYW5ndWFnZS1zZXJ2aWNlLnNwZWMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJoZWxsb1wiKSJdLCJ2ZXJzaW9uIjozfQ==
57+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1jYWNoZS50cyIsIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbInRlc3QtY2FjaGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJoZWxsb1wiKSJdLCJ2ZXJzaW9uIjozfQ==
3058
===[ INLINE SOURCE MAPS ]=======================================================
31-
file: <cwd>/src/compiler/language-service.spec.ts
59+
file: test-cache.ts
3260
mappings: 'AAAA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA'
3361
names: []
3462
sources:
35-
- <cwd>/src/compiler/language-service.spec.ts
63+
- test-cache.ts
3664
sourcesContent:
3765
- console.log("hello")
3866
version: 3

‎src/compiler/__snapshots__/program.spec.ts.snap

+56
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,62 @@ exports[`allowJs should compile js file for allowJs true with normal program 1`]
3636
================================================================================
3737
`;
3838

39+
exports[`cannot compile should throw error with incremental program 1`] = `
40+
"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
41+
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\`."
42+
`;
43+
44+
exports[`cannot compile should throw error with normal program 1`] = `
45+
"Unable to require \`.d.ts\` file for file: test-cannot-compile.d.ts.
46+
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\`."
47+
`;
48+
49+
exports[`jsx preserve should compile tsx file for jsx preserve with incremental program 1`] = `
50+
===[ FILE: test-jsx-preserve.tsx ]==============================================
51+
var App = function () {
52+
return <>Test</>;
53+
};
54+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNNLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICBjb25zdCBBcHAgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgIH1cbiAgICAiXSwidmVyc2lvbiI6M30=
55+
===[ INLINE SOURCE MAPS ]=======================================================
56+
file: test-jsx-preserve.tsx
57+
mappings: 'AACM,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
58+
names: []
59+
sources:
60+
- test-jsx-preserve.tsx
61+
sourcesContent:
62+
- |2-
63+
64+
const App = () => {
65+
return <>Test</>
66+
}
67+
68+
version: 3
69+
================================================================================
70+
`;
71+
72+
exports[`jsx preserve should compile tsx file for jsx preserve with program 1`] = `
73+
===[ FILE: test-jsx-preserve.tsx ]==============================================
74+
var App = function () {
75+
return <>Test</>;
76+
};
77+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiJBQUNNLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxFQUFFLElBQUksR0FBRyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1wcmVzZXJ2ZS50c3giXSwic291cmNlc0NvbnRlbnQiOlsiXG4gICAgICBjb25zdCBBcHAgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgIH1cbiAgICAiXSwidmVyc2lvbiI6M30=
78+
===[ INLINE SOURCE MAPS ]=======================================================
79+
file: test-jsx-preserve.tsx
80+
mappings: 'AACM,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
81+
names: []
82+
sources:
83+
- test-jsx-preserve.tsx
84+
sourcesContent:
85+
- |2-
86+
87+
const App = () => {
88+
return <>Test</>
89+
}
90+
91+
version: 3
92+
================================================================================
93+
`;
94+
3995
exports[`typings incremental program should report diagnostics with pathRegex config matches file name 1`] = `"test-typings.ts: Emit skipped"`;
4096

4197
exports[`typings normal program should report diagnostics with pathRegex config matches file name 1`] = `

‎src/compiler/__snapshots__/transpile-module.spec.ts.snap

+23
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,29 @@ exports[`transpile module with isolatedModule: true should compile js file for a
1818
================================================================================
1919
`;
2020
21+
exports[`transpile module with isolatedModule: true should compile tsx file for jsx preserve 1`] = `
22+
===[ FILE: foo.tsx ]============================================================
23+
var App = function () {
24+
return <>Test</>;
25+
};
26+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiZm9vLnRzeCIsIm1hcHBpbmdzIjoiQUFDUSxJQUFNLEdBQUcsR0FBRztJQUNWLE9BQU8sRUFBRSxJQUFJLEdBQUcsQ0FBQTtBQUNsQixDQUFDLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZm9vLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAgICAgY29uc3QgQXBwID0gKCkgPT4ge1xuICAgICAgICAgIHJldHVybiA8PlRlc3Q8Lz5cbiAgICAgICAgfVxuICAgICAgIl0sInZlcnNpb24iOjN9
27+
===[ INLINE SOURCE MAPS ]=======================================================
28+
file: foo.tsx
29+
mappings: 'AACQ,IAAM,GAAG,GAAG;IACV,OAAO,EAAE,IAAI,GAAG,CAAA;AAClB,CAAC,CAAA'
30+
names: []
31+
sources:
32+
- foo.tsx
33+
sourcesContent:
34+
- |2-
35+
36+
const App = () => {
37+
return <>Test</>
38+
}
39+
40+
version: 3
41+
================================================================================
42+
`;
43+
2144
exports[`transpile module with isolatedModule: true should compile using transpileModule and not use cache 1`] = `
2245
===[ FILE: src/compiler/transpile-module.spec.ts ]==============================
2346
"use strict";

‎src/compiler/instance.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,9 @@ export const createCompiler = (configs: ConfigSet): TsCompiler => {
175175
let compileResult: CompileResult
176176
if (!tsJest.isolatedModules) {
177177
// Use language services by default
178-
if (!tsJest.compilerHost) {
179-
compileResult = compileUsingLanguageService(configs, logger, memoryCache)
180-
} else {
181-
compileResult = compileUsingProgram(configs, logger, memoryCache)
182-
}
178+
compileResult = !tsJest.compilerHost
179+
? compileUsingLanguageService(configs, logger, memoryCache)
180+
: compileUsingProgram(configs, logger, memoryCache)
183181
} else {
184182
compileResult = compileUsingTranspileModule(configs, logger)
185183
}

‎src/compiler/language-service.spec.ts

+57-13
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ describe('language service', () => {
1919
jestConfig: { cache: true, cacheDirectory: tmp },
2020
tsJestConfig: { tsConfig: false },
2121
}),
22-
source = 'console.log("hello")'
22+
source = 'console.log("hello")',
23+
fileName = 'test-cache.ts'
24+
25+
writeFileSync(fileName, source, 'utf8')
2326

2427
logTarget.clear()
25-
const compiled1 = compiler.compile(source, __filename)
28+
const compiled1 = compiler.compile(source, fileName)
2629

2730
expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(`
2831
Array [
@@ -44,7 +47,7 @@ describe('language service', () => {
4447
`)
4548

4649
logTarget.clear()
47-
const compiled2 = compiler.compile(source, __filename)
50+
const compiled2 = compiler.compile(source, fileName)
4851

4952
expect(logTarget.lines).toMatchInlineSnapshot(`
5053
Array [
@@ -53,12 +56,14 @@ describe('language service', () => {
5356
]
5457
`)
5558

56-
expect(new ProcessedSource(compiled1, __filename)).toMatchSnapshot()
59+
expect(new ProcessedSource(compiled1, fileName)).toMatchSnapshot()
5760
expect(compiled2).toBe(compiled1)
61+
62+
removeSync(fileName)
5863
})
5964

6065
it('should compile js file for allowJs true', () => {
61-
const fileName = `foo.test.js`,
66+
const fileName = `test-allow-js.js`,
6267
compiler = makeCompiler({
6368
tsJestConfig: { tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } },
6469
}),
@@ -72,27 +77,49 @@ describe('language service', () => {
7277
removeSync(fileName)
7378
})
7479

80+
it('should compile tsx file for jsx preserve', () => {
81+
const fileName = 'test-jsx-preserve.tsx',
82+
compiler = makeCompiler({
83+
tsJestConfig: { tsConfig: 'src/__mocks__/tsconfig.json' },
84+
}),
85+
source = `
86+
const App = () => {
87+
return <>Test</>
88+
}
89+
`
90+
writeFileSync(fileName, source, 'utf8')
91+
const compiled = compiler.compile(source, fileName)
92+
93+
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
94+
95+
removeSync(fileName)
96+
})
97+
7598
it('should have correct source maps', () => {
7699
const compiler = makeCompiler({ tsJestConfig: { tsConfig: false } }),
77-
source = 'const g = (v: number) => v\nconst h: number = g(5)'
100+
source = 'const gsm = (v: number) => v\nconst h: number = gsm(5)',
101+
fileName = 'test-source-map.ts'
102+
writeFileSync(fileName, source, 'utf8')
78103

79-
const compiled = compiler.compile(source, 'foo.ts')
104+
const compiled = compiler.compile(source, fileName)
80105

81-
expect(new ProcessedSource(compiled, 'foo.ts').outputSourceMaps).toMatchObject({
82-
file: 'foo.ts',
83-
sources: ['foo.ts'],
106+
expect(new ProcessedSource(compiled, fileName).outputSourceMaps).toMatchObject({
107+
file: fileName,
108+
sources: [fileName],
84109
sourcesContent: [source],
85110
})
111+
112+
removeSync(fileName)
86113
})
87114

88115
it('should report diagnostics related to typings with pathRegex config matches file name', () => {
89-
const fileName = 'foo.ts',
116+
const fileName = 'test-match-regex-diagnostics.ts',
90117
source = `
91118
const g = (v: number) => v
92119
const x: string = g(5)
93120
`,
94121
compiler = makeCompiler({
95-
tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: 'foo.ts' } },
122+
tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: fileName } },
96123
})
97124
writeFileSync(fileName, source, 'utf8')
98125

@@ -102,7 +129,7 @@ const x: string = g(5)
102129
})
103130

104131
it('should not report diagnostics related to typings with pathRegex config does not match file name', () => {
105-
const fileName = 'foo.ts',
132+
const fileName = 'test-non-match-regex-diagnostics.ts',
106133
source = `
107134
const f = (v: number) => v
108135
const t: string = f(5)
@@ -116,4 +143,21 @@ const t: string = f(5)
116143

117144
removeSync(fileName)
118145
})
146+
147+
it('should throw error when cannot compile', () => {
148+
const fileName = 'test-cannot-compile.d.ts',
149+
source = `
150+
interface Foo {
151+
a: string
152+
}
153+
`,
154+
compiler = makeCompiler({
155+
tsJestConfig: { tsConfig: false },
156+
})
157+
writeFileSync(fileName, source, 'utf8')
158+
159+
expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
160+
161+
removeSync(fileName)
162+
})
119163
})

‎src/compiler/language-service.ts

-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ export const compileUsingLanguageService = (
124124

125125
previousProgram = programAfter
126126
// Throw an error when requiring `.d.ts` files.
127-
/* istanbul ignore next (this should never happen but is kept for security) */
128127
if (!output.outputFiles.length) {
129128
throw new TypeError(
130129
interpolate(Errors.UnableToRequireDefinitionFile, {

‎src/compiler/program.spec.ts

+100-27
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const t: string = f(5)
3333
const compiler = makeCompiler({
3434
tsJestConfig: {
3535
...baseTsJestConfig,
36-
tsConfig: { incremental: false },
36+
incremental: false,
3737
diagnostics: { pathRegex: fileName },
3838
},
3939
})
@@ -45,7 +45,7 @@ const t: string = f(5)
4545
const compiler = makeCompiler({
4646
tsJestConfig: {
4747
...baseTsJestConfig,
48-
tsConfig: { incremental: false },
48+
incremental: false,
4949
diagnostics: { pathRegex: 'foo.ts' },
5050
},
5151
})
@@ -63,7 +63,7 @@ const t: string = f(5)
6363
const compiler = makeCompiler({
6464
tsJestConfig: {
6565
...baseTsJestConfig,
66-
tsConfig: { incremental: true },
66+
incremental: true,
6767
diagnostics: { pathRegex: 'typings-error.ts' },
6868
},
6969
})
@@ -75,7 +75,7 @@ const t: string = f(5)
7575
const compiler = makeCompiler({
7676
tsJestConfig: {
7777
...baseTsJestConfig,
78-
tsConfig: { incremental: true },
78+
incremental: true,
7979
diagnostics: { pathRegex: 'foo.ts' },
8080
},
8181
})
@@ -105,7 +105,7 @@ describe('source-maps', () => {
105105
const compiler = makeCompiler({
106106
tsJestConfig: {
107107
...baseTsJestConfig,
108-
tsConfig: { incremental: false },
108+
incremental: false,
109109
},
110110
})
111111

@@ -122,7 +122,7 @@ describe('source-maps', () => {
122122
const compiler = makeCompiler({
123123
tsJestConfig: {
124124
...baseTsJestConfig,
125-
tsConfig: { incremental: true },
125+
incremental: true,
126126
},
127127
})
128128

@@ -137,8 +137,7 @@ describe('source-maps', () => {
137137
})
138138

139139
describe('cache', () => {
140-
const tmp = tempDir('compiler'),
141-
fileName = 'test-cache.ts',
140+
const fileName = 'test-cache.ts',
142141
source = 'console.log("hello")'
143142

144143
beforeAll(() => {
@@ -150,13 +149,14 @@ describe('cache', () => {
150149
})
151150

152151
it('should use the cache with normal program', () => {
153-
const compiler = makeCompiler({
154-
jestConfig: { cache: true, cacheDirectory: tmp },
155-
tsJestConfig: {
156-
...baseTsJestConfig,
157-
tsConfig: { incremental: false },
158-
},
159-
})
152+
const tmp = tempDir('program-compiler'),
153+
compiler = makeCompiler({
154+
jestConfig: { cache: true, cacheDirectory: tmp },
155+
tsJestConfig: {
156+
...baseTsJestConfig,
157+
incremental: false,
158+
},
159+
})
160160

161161
logTarget.clear()
162162
const compiled1 = compiler.compile(source, fileName)
@@ -187,22 +187,23 @@ describe('cache', () => {
187187
expect(compiled2).toBe(compiled1)
188188
})
189189

190-
it('should use the cache with normal program', () => {
191-
const compiler = makeCompiler({
192-
jestConfig: { cache: true, cacheDirectory: tmp },
193-
tsJestConfig: {
194-
...baseTsJestConfig,
195-
tsConfig: { incremental: true },
196-
},
197-
})
190+
it('should use the cache with incremental program', () => {
191+
const tmp = tempDir('incremental-program-compiler'),
192+
compiler = makeCompiler({
193+
jestConfig: { cache: true, cacheDirectory: tmp },
194+
tsJestConfig: {
195+
...baseTsJestConfig,
196+
incremental: true,
197+
},
198+
})
198199

199200
logTarget.clear()
200201
const compiled1 = compiler.compile(source, fileName)
201202
expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(`
202203
Array [
203204
"[level:20] readThrough(): cache miss
204205
",
205-
"[level:20] updateMemoryCache() for program
206+
"[level:20] updateMemoryCache() for incremental program
206207
",
207208
"[level:20] visitSourceFileNode(): hoisting
208209
",
@@ -228,7 +229,8 @@ Array [
228229

229230
describe('allowJs', () => {
230231
const fileName = 'test-allowJs.test.js',
231-
source = 'export default 42'
232+
source = 'export default 42',
233+
tsConfig = { allowJs: true, outDir: '$$ts-jest$$' }
232234

233235
beforeAll(() => {
234236
writeFileSync(fileName, source, 'utf8')
@@ -240,7 +242,7 @@ describe('allowJs', () => {
240242

241243
it('should compile js file for allowJs true with normal program', () => {
242244
const compiler = makeCompiler({
243-
tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$', incremental: false } },
245+
tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig },
244246
})
245247

246248
const compiled = compiler.compile(source, fileName)
@@ -250,11 +252,82 @@ describe('allowJs', () => {
250252

251253
it('should compile js file for allowJs true with incremental program', () => {
252254
const compiler = makeCompiler({
253-
tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$', incremental: true } },
255+
tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig },
254256
})
255257

256258
const compiled = compiler.compile(source, fileName)
257259

258260
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
259261
})
260262
})
263+
264+
describe('jsx preserve', () => {
265+
const fileName = 'test-jsx-preserve.tsx',
266+
source = `
267+
const App = () => {
268+
return <>Test</>
269+
}
270+
`,
271+
tsConfig = 'src/__mocks__/tsconfig.json'
272+
273+
beforeAll(() => {
274+
writeFileSync(fileName, source, 'utf8')
275+
})
276+
277+
afterAll(() => {
278+
removeSync(fileName)
279+
})
280+
281+
it('should compile tsx file for jsx preserve with program', () => {
282+
const compiler = makeCompiler({
283+
tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig },
284+
})
285+
286+
const compiled = compiler.compile(source, fileName)
287+
288+
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
289+
})
290+
291+
it('should compile tsx file for jsx preserve with incremental program', () => {
292+
const compiler = makeCompiler({
293+
tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig },
294+
})
295+
296+
const compiled = compiler.compile(source, fileName)
297+
298+
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
299+
})
300+
})
301+
302+
describe('cannot compile', () => {
303+
const fileName = 'test-cannot-compile.d.ts',
304+
source = `
305+
interface Foo {
306+
a: string
307+
}
308+
`
309+
310+
beforeAll(() => {
311+
writeFileSync(fileName, source, 'utf8')
312+
})
313+
314+
afterAll(() => {
315+
removeSync(fileName)
316+
})
317+
318+
it('should throw error with normal program', () => {
319+
const compiler = makeCompiler({
320+
tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig: false },
321+
})
322+
323+
expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
324+
})
325+
326+
it('should throw error with incremental program', () => {
327+
const compiler = makeCompiler({
328+
tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig: false },
329+
})
330+
331+
expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot()
332+
})
333+
})

‎src/compiler/program.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
1515

1616
const ts = configs.compilerModule,
1717
cwd = configs.cwd,
18-
{ options, fileNames, projectReferences, errors } = configs.typescript
18+
{ options, fileNames, projectReferences, errors } = configs.typescript,
19+
incremental = configs.tsJest.incremental
1920
const compilerHostTraceCtx = {
2021
namespace: 'ts:compilerHost',
2122
call: null,
@@ -36,8 +37,9 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
3637
ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
3738
}
3839
let builderProgram: _ts.EmitAndSemanticDiagnosticsBuilderProgram, program: _ts.Program, host: _ts.CompilerHost
39-
// Fallback for older TypeScript releases without incremental API.
40-
if (options.incremental) {
40+
if (incremental) {
41+
// TODO: Find a way to trigger typescript to build project when there are project references.
42+
// At the moment this Incremental Program doesn't work with project references
4143
host = ts.createIncrementalCompilerHost(options, sys)
4244
builderProgram = ts.createIncrementalProgram({
4345
rootNames: fileNames.slice(),
@@ -48,6 +50,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
4850
})
4951
program = builderProgram.getProgram()
5052
} else {
53+
// Fallback for older TypeScript releases without incremental API.
5154
host = {
5255
...sys,
5356
getSourceFile: (fileName, languageVersion) => {
@@ -71,7 +74,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
7174
// Read and cache custom transformers.
7275
const customTransformers = configs.tsCustomTransformers,
7376
updateMemoryCache = (contents: string, normalizedFileName: string): void => {
74-
logger.debug({ normalizedFileName }, `updateMemoryCache() for program`)
77+
logger.debug({ normalizedFileName }, `updateMemoryCache() for ${incremental ? 'incremental program' : 'program'}`)
7578

7679
const fileVersion = memoryCache.versions.get(normalizedFileName) ?? 0,
7780
isFileInCache = fileVersion !== 0
@@ -84,7 +87,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
8487
memoryCache.versions.set(normalizedFileName, fileVersion + 1)
8588
memoryCache.contents.set(normalizedFileName, contents)
8689
}
87-
const sourceFile = options.incremental
90+
const sourceFile = incremental
8891
? builderProgram.getSourceFile(normalizedFileName)
8992
: program.getSourceFile(normalizedFileName)
9093
// Update program when file changes.
@@ -100,7 +103,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
100103
configFileParsingDiagnostics: errors,
101104
projectReferences,
102105
}
103-
if (options.incremental) {
106+
if (incremental) {
104107
builderProgram = ts.createIncrementalProgram(programOptions)
105108
program = builderProgram.getProgram()
106109
} else {
@@ -114,13 +117,13 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
114117
output: [string, string] = ['', '']
115118
// Must set memory cache before attempting to read file.
116119
updateMemoryCache(code, normalizedFileName)
117-
const sourceFile = options.incremental
120+
const sourceFile = incremental
118121
? builderProgram.getSourceFile(normalizedFileName)
119122
: program.getSourceFile(normalizedFileName)
120123

121124
if (!sourceFile) throw new TypeError(`Unable to read file: ${fileName}`)
122125

123-
const result: _ts.EmitResult = options.incremental
126+
const result: _ts.EmitResult = incremental
124127
? builderProgram.emit(
125128
sourceFile,
126129
(path, file, _writeByteOrderMark) => {
@@ -142,7 +145,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
142145
if (configs.shouldReportDiagnostic(normalizedFileName)) {
143146
logger.debug(
144147
{ normalizedFileName },
145-
`getOutput(): computing diagnostics for ${options.incremental ? 'incremental program' : 'program'}`,
148+
`getOutput(): computing diagnostics for ${incremental ? 'incremental program' : 'program'}`,
146149
)
147150
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile).slice()
148151
// will raise or just warn diagnostics depending on config
@@ -165,7 +168,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa
165168
}),
166169
)
167170
}
168-
if (configs.tsJest.emit && options.incremental) {
171+
if (configs.tsJest.emit && incremental) {
169172
process.on('exit', () => {
170173
// Emits `.tsbuildinfo` to filesystem.
171174
// @ts-ignore

‎src/compiler/transpile-module.spec.ts

+19
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ describe('transpile module with isolatedModule: true', () => {
5454
removeSync(fileName)
5555
})
5656

57+
it('should compile tsx file for jsx preserve', () => {
58+
const fileName = `foo.tsx`,
59+
compiler = makeCompiler({
60+
tsJestConfig: { ...baseTsJestConfig, tsConfig: 'src/__mocks__/tsconfig.json' },
61+
}),
62+
source = `
63+
const App = () => {
64+
return <>Test</>
65+
}
66+
`
67+
68+
writeFileSync(fileName, source, 'utf8')
69+
const compiled = compiler.compile(source, fileName)
70+
71+
expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot()
72+
73+
removeSync(fileName)
74+
})
75+
5776
it('should have correct source maps', () => {
5877
const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }),
5978
source = 'const f = (v: number) => v\nconst t: number = f(5)'

‎src/config/__snapshots__/config-set.spec.ts.snap

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Object {
5353
"throws": true,
5454
},
5555
"emit": false,
56+
"incremental": true,
5657
"isolatedModules": false,
5758
"packageJson": Object {
5859
"kind": "file",
@@ -143,6 +144,7 @@ Object {
143144
"throws": true,
144145
},
145146
"emit": false,
147+
"incremental": true,
146148
"isolatedModules": false,
147149
"packageJson": Object {
148150
"kind": "file",

‎src/config/config-set.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ describe('cacheKey', () => {
966966
cs.jsonValue.value = val
967967
// digest is mocked in src/__mocks__/index.ts
968968
expect(cs.cacheKey).toMatchInlineSnapshot(
969-
`"{\\"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}}"`,
969+
`"{\\"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}}"`,
970970
)
971971
})
972972
}) // cacheKey

‎src/config/config-set.ts

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ export class ConfigSet {
266266
const res: TsJestConfig = {
267267
tsConfig,
268268
compilerHost: options.compilerHost ?? false,
269+
incremental: options.incremental ?? true,
269270
emit: options.emit ?? false,
270271
packageJson,
271272
babelConfig,

‎src/ts-jest-transformer.spec.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import { ConfigSet } from './config/config-set'
88
import { TsJestTransformer } from './ts-jest-transformer'
99

1010
describe('configFor', () => {
11-
it('should return the same config-set for same values', () => {
11+
it('should return the same config-set for same values with jest config string is not in configSetsIndex', () => {
12+
const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
13+
const str = stringify(obj1)
14+
const cs3 = new TsJestTransformer().configsFor(str)
15+
expect(cs3.cwd).toBe(`${sep}foo`)
16+
expect(cs3.rootDir).toBe(`${sep}bar`)
17+
})
18+
19+
it('should return the same config-set for same values with jest config string in configSetsIndex', () => {
1220
const obj1 = { cwd: '/foo/.', rootDir: '/bar//dummy/..', globals: {} }
1321
const obj2 = { ...obj1 }
1422
const str = stringify(obj1)
@@ -70,12 +78,12 @@ describe('process', () => {
7078
it('should process ts input without babel', () => {
7179
expect(process()).toBe(`ts:${INPUT}`)
7280
expect(config.shouldStringifyContent.mock.calls).toMatchInlineSnapshot(`
73-
Array [
74-
Array [
75-
"/foo/bar.ts",
76-
],
77-
]
78-
`)
81+
Array [
82+
Array [
83+
"/foo/bar.ts",
84+
],
85+
]
86+
`)
7987
expect(config.tsCompiler.compile.mock.calls).toMatchInlineSnapshot(`
8088
Array [
8189
Array [
@@ -194,6 +202,11 @@ Array [
194202
`)
195203
})
196204

205+
it('should return empty string when trying to process definition file types', () => {
206+
args[1] = '/foo/bar.d.ts'
207+
expect(process()).toBe('')
208+
})
209+
197210
it('should warn when trying to process unknown file types', () => {
198211
args[1] = '/foo/bar.jest'
199212
const logs = logTargetMock()

‎src/ts-jest-transformer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class TsJestTransformer implements Transformer {
6262
return `[object TsJestTransformer<#${this.id}>]`
6363
}
6464

65-
configsFor(jestConfig: Config.ProjectConfig | string) {
65+
configsFor(jestConfig: Config.ProjectConfig | string): ConfigSet {
6666
let csi: ConfigSetIndexItem | undefined
6767
let jestConfigObj: Config.ProjectConfig
6868
if (typeof jestConfig === 'string') {

‎src/types.ts

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ export interface TsJestGlobalOptions {
4444
*/
4545
compilerHost?: boolean
4646

47+
/**
48+
* Use TypeScript's Incremental Program. This option only works when `compilerHost` is `true`
49+
* TODO: Remove this flag when we can make project references working with our Incremental Program
50+
* @default false
51+
*/
52+
incremental?: boolean
53+
4754
/**
4855
* Emit compiled files into `.ts-jest` directory
4956
*
@@ -142,6 +149,7 @@ export interface TsJestConfig {
142149
packageJson: TsJestConfig$packageJson
143150
isolatedModules: boolean
144151
compilerHost: boolean
152+
incremental: boolean // TODO: Remove this flag when we can make project references working with our Incremental Program
145153
emit: boolean
146154
compiler: string
147155
diagnostics: TsJestConfig$diagnostics

0 commit comments

Comments
 (0)
Please sign in to comment.