diff --git a/docs/user/config/compilerHost.md b/docs/user/config/compilerHost.md index 8bc398c47a..72bb5c296b 100644 --- a/docs/user/config/compilerHost.md +++ b/docs/user/config/compilerHost.md @@ -3,21 +3,15 @@ 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`. +But TypeScript `Incremental 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: +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. +- `compilerHost` is enabled: use TypeScript `Incremental Program`. +- `isolatedModules` is enabled: use TypeScript transpile modules. -Here is how to enable `ts-jest` to compile using TypeScript `Program` +Here is how to enable `ts-jest` to compile using TypeScript `Incremental Program` ### Example @@ -30,7 +24,6 @@ module.exports = { globals: { 'ts-jest': { compilerHost: true, - incremental: false, } } }; @@ -46,44 +39,6 @@ module.exports = { "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 cd93769a70..66f4854f16 100644 --- a/docs/user/config/index.md +++ b/docs/user/config/index.md @@ -191,7 +191,6 @@ All options have default values which should fit most of the projects. Click on | [**`tsConfig`**][tsConfig] | [TypeScript compiler related configuration.][tsConfig] | `string`\|`object`\|`boolean` | _auto_ | | [**`isolatedModules`**][isolatedModules] | [Disable type-checking][isolatedModules] | `boolean` | `false` | | [**`compilerHost`**][compilerHost] | [Use TypeScript Compiler API][compilerHost] | `boolean` | `false` | -| [**`incremental (use with `compilerHost`)`**][compilerHost] | [Use TypeScript Incremental Program][compilerHost] | `boolean` | `true` | | [**`diagnostics`**][diagnostics] | [Diagnostics related configuration.][diagnostics] | `boolean`\|`object` | `true` | | [**`babelConfig`**][babelConfig] | [Babel(Jest) related configuration.][babelConfig] | `boolean`\|`object` | _disabled_ | | [**`stringifyContentPathRegex`**][stringifyContentPathRegex] | [Files which will become modules returning self content.][stringifyContentPathRegex] | `string`\|`RegExp` | _disabled_ | diff --git a/e2e/__external-repos__/simple/with-dependency/package.json b/e2e/__external-repos__/simple/with-dependency/package.json index 1f4d55b21a..d0c64b6486 100644 --- a/e2e/__external-repos__/simple/with-dependency/package.json +++ b/e2e/__external-repos__/simple/with-dependency/package.json @@ -31,8 +31,7 @@ "globals": { "ts-jest": { "diagnostics": true, - "tsConfig": "/tsconfig.json", - "compilerHost": true + "tsConfig": "/tsconfig.json" } } }, diff --git a/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap b/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap index cd5b2dd025..0d71656481 100644 --- a/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap +++ b/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap @@ -462,237 +462,6 @@ exports[`With diagnostics throw using language service then pass when type has c ================================================================================ `; -exports[`With diagnostics throw using program first throw should fail using template "default" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - ● Test suite failed to run - - main.spec.ts:3:14 - error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'. - - 3 export const thing: Thing = { a: 1 }; - ~~~~~ - - main.ts:2:34 - 2 export type Thing = { a: number, b: number } - ~ - 'b' is declared here. - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program first throw should fail using template "with-babel-7" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - ● Test suite failed to run - - main.spec.ts:3:14 - error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'. - - 3 export const thing: Thing = { a: 1 }; - ~~~~~ - - main.ts:2:34 - 2 export type Thing = { a: number, b: number } - ~ - 'b' is declared here. - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program first throw should fail using template "with-babel-7-string-config" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - ● Test suite failed to run - - main.spec.ts:3:14 - error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'. - - 3 export const thing: Thing = { a: 1 }; - ~~~~~ - - main.ts:2:34 - 2 export type Thing = { a: number, b: number } - ~ - 'b' is declared here. - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then failed when type has changed to invalid base on cache of the previous run should fail using template "default" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - × foo is 42 - - ● foo is 42 - - expect(received).toBe(expected) // Object.is equality - - Expected: 42 - Received: 43 - - 4 | - 5 | test('foo is 42', () => { - > 6 | expect(foo).toBe(42); - | ^ - 7 | }); - 8 | - - at Object. (main.spec.ts:6:15) - - Test Suites: 1 failed, 1 total - Tests: 1 failed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then failed when type has changed to invalid base on cache of the previous run should fail using template "with-babel-7" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - × foo is 42 - - ● foo is 42 - - expect(received).toBe(expected) // Object.is equality - - Expected: 42 - Received: 43 - - 4 | - 5 | test('foo is 42', () => { - > 6 | expect(foo).toBe(42); - | ^ - 7 | }); - 8 | - - at Object. (main.spec.ts:6:15) - - Test Suites: 1 failed, 1 total - Tests: 1 failed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then failed when type has changed to invalid base on cache of the previous run should fail using template "with-babel-7-string-config" 1`] = ` - × jest - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - × foo is 42 - - ● foo is 42 - - expect(received).toBe(expected) // Object.is equality - - Expected: 42 - Received: 43 - - 4 | - 5 | test('foo is 42', () => { - > 6 | expect(foo).toBe(42); - | ^ - 7 | }); - 8 | - - at Object. (main.spec.ts:6:15) - - Test Suites: 1 failed, 1 total - Tests: 1 failed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then pass when type has changed to valid base on cache of the previous run should pass using template "default" 1`] = ` - √ jest - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - PASS ./main.spec.ts - √ foo is 42 - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then pass when type has changed to valid base on cache of the previous run should pass using template "with-babel-7" 1`] = ` - √ jest - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - PASS ./main.spec.ts - √ foo is 42 - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With diagnostics throw using program then pass when type has changed to valid base on cache of the previous run should pass using template "with-babel-7-string-config" 1`] = ` - √ jest - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - PASS ./main.spec.ts - √ foo is 42 - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - exports[`With diagnostics warn only should pass using template "default" 1`] = ` √ jest --no-cache ↳ exit code: 0 diff --git a/e2e/__tests__/diagnostics.test.ts b/e2e/__tests__/diagnostics.test.ts index 3a43fc491c..c2ff77251e 100644 --- a/e2e/__tests__/diagnostics.test.ts +++ b/e2e/__tests__/diagnostics.test.ts @@ -55,66 +55,10 @@ describe('With diagnostics throw', () => { }) }) - describe('using program', () => { - const testCase = configureTestCase('diagnostics/throw', { - tsJestConfig: { - compilerHost: true, - incremental: false, - }, - }) - - describe('first throw', () => { - testCase.runWithTemplates(allPackageSetsWithProgram, 1, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(1) - expect(result).toMatchSnapshot() - }) - }) - }) - - describe('then pass when type has changed to valid base on cache of the previous run', () => { - beforeAll(() => { - writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number }`) - }) - - afterAll(() => { - writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`) - }) - - testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(0) - expect(result).toMatchSnapshot() - }) - }) - }) - - describe('then failed when type has changed to invalid base on cache of the previous run', () => { - beforeAll(() => { - writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 43\nexport type Thing = { a: number }`) - }) - - afterAll(() => { - writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`) - }) - - testCase.runWithTemplates(allPackageSetsWithProgram, 1, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(1) - expect(result).toMatchSnapshot() - }) - }) - }) - }) - describe('using incremental program', () => { const testCase = configureTestCase('diagnostics/throw', { tsJestConfig: { compilerHost: true, - incremental: true, }, }) diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts index 9ebaeef92b..8655284f4b 100644 --- a/src/__helpers__/fakers.ts +++ b/src/__helpers__/fakers.ts @@ -15,7 +15,6 @@ export const rootDir = filePath('') export function tsJestConfig(options?: Partial): TsJestConfig { return { compilerHost: false, - incremental: false, isolatedModules: false, compiler: 'typescript', transformers: [], diff --git a/src/compiler/__snapshots__/program.spec.ts.snap b/src/compiler/__snapshots__/program.spec.ts.snap index 906c4af532..08c8fb5d77 100644 --- a/src/compiler/__snapshots__/program.spec.ts.snap +++ b/src/compiler/__snapshots__/program.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`allowJs with incremental program should compile js file for allowJs true with outDir 1`] = ` +exports[`allowJs should compile js file for allowJs true with outDir 1`] = ` ===[ FILE: test-allowJs-incremental-outDir.test.js ]============================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); @@ -18,7 +18,7 @@ exports[`allowJs with incremental program should compile js file for allowJs tru ================================================================================ `; -exports[`allowJs with incremental program should compile js file for allowJs true without outDir 1`] = ` +exports[`allowJs should compile js file for allowJs true without outDir 1`] = ` ===[ FILE: test-allowJs-incremental-no-outDir.test.js ]========================= "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); @@ -36,85 +36,16 @@ exports[`allowJs with incremental program should compile js file for allowJs tru ================================================================================ `; -exports[`allowJs with program should compile js file for allowJs true with outDir 1`] = ` - ===[ FILE: test-allowJs-program-outDir.test.js ]================================ - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = 42; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1hbGxvd0pzLXByb2dyYW0tb3V0RGlyLnRlc3QuanMiLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZSxFQUFFLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsidGVzdC1hbGxvd0pzLXByb2dyYW0tb3V0RGlyLnRlc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgNDIiXSwidmVyc2lvbiI6M30= - ===[ INLINE SOURCE MAPS ]======================================================= - file: test-allowJs-program-outDir.test.js - mappings: ';;AAAA,kBAAe,EAAE,CAAA' - names: [] - sources: - - test-allowJs-program-outDir.test.js - sourcesContent: - - export default 42 - version: 3 - ================================================================================ -`; - -exports[`allowJs with program should compile js file for allowJs true without outDir 1`] = ` - ===[ FILE: test-allowJs-program-no-outDir.test.js ]============================= - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.default = 42; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1hbGxvd0pzLXByb2dyYW0tbm8tb3V0RGlyLnRlc3QuanMiLCJtYXBwaW5ncyI6Ijs7QUFBQSxrQkFBZSxFQUFFLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsidGVzdC1hbGxvd0pzLXByb2dyYW0tbm8tb3V0RGlyLnRlc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgNDIiXSwidmVyc2lvbiI6M30= - ===[ INLINE SOURCE MAPS ]======================================================= - file: test-allowJs-program-no-outDir.test.js - mappings: ';;AAAA,kBAAe,EAAE,CAAA' - names: [] - sources: - - test-allowJs-program-no-outDir.test.js - sourcesContent: - - export default 42 - version: 3 - ================================================================================ -`; - -exports[`cannot compile should throw error with incremental program 1`] = ` +exports[`cannot compile should throw error 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 incremental program 2`] = `"Unable to read file: test-cannot-compile.jsx"`; - -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[`cannot compile should throw error 2`] = `"Unable to read file: test-cannot-compile.jsx"`; -exports[`cannot compile should throw error with normal program 2`] = `"Unable to read file: test-cannot-compile.jsx"`; - -exports[`diagnostics incremental program should report diagnostics with pathRegex config matches file name 1`] = `"test-typings.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`; - -exports[`diagnostics normal program should report diagnostics with pathRegex config matches file name 1`] = `"test-typings.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`; - -exports[`jsx preserve should compile tsx file for with incremental program 1`] = ` - ===[ FILE: test-jsx-preserve.tsx ]============================================== - "use strict"; - var App = function () { - return <>Test; - }; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtcHJlc2VydmUudHN4IiwibWFwcGluZ3MiOiI7QUFDTSxJQUFNLEdBQUcsR0FBRztJQUNWLE9BQU8sRUFBRSxJQUFJLEdBQUcsQ0FBQTtBQUNsQixDQUFDLENBQUEiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsidGVzdC1qc3gtcHJlc2VydmUudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIlxuICAgICAgY29uc3QgQXBwID0gKCkgPT4ge1xuICAgICAgICByZXR1cm4gPD5UZXN0PC8+XG4gICAgICB9XG4gICAgIl0sInZlcnNpb24iOjN9 - ===[ 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[`diagnostics should report diagnostics with pathRegex config matches file name 1`] = `"test-typings.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`; -exports[`jsx preserve should compile tsx file with program 1`] = ` +exports[`jsx preserve should compile tsx file 1`] = ` ===[ FILE: test-jsx-preserve.tsx ]============================================== "use strict"; var App = function () { @@ -138,31 +69,7 @@ exports[`jsx preserve should compile tsx file with program 1`] = ` ================================================================================ `; -exports[`other jsx options should compile tsx file for with incremental program 1`] = ` - ===[ FILE: test-jsx-options.tsx ]=============================================== - "use strict"; - var App = function () { - return React.createElement(React.Fragment, null, "Test"); - }; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC1qc3gtb3B0aW9ucy50c3giLCJtYXBwaW5ncyI6IjtBQUNNLElBQU0sR0FBRyxHQUFHO0lBQ1YsT0FBTyxpREFBUyxDQUFBO0FBQ2xCLENBQUMsQ0FBQSIsIm5hbWVzIjpbXSwic291cmNlcyI6WyJ0ZXN0LWpzeC1vcHRpb25zLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAgIGNvbnN0IEFwcCA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIDw+VGVzdDwvPlxuICAgICAgfVxuICAgICJdLCJ2ZXJzaW9uIjozfQ== - ===[ INLINE SOURCE MAPS ]======================================================= - file: test-jsx-options.tsx - mappings: ';AACM,IAAM,GAAG,GAAG;IACV,OAAO,iDAAS,CAAA;AAClB,CAAC,CAAA' - names: [] - sources: - - test-jsx-options.tsx - sourcesContent: - - |2- - - const App = () => { - return <>Test - } - - version: 3 - ================================================================================ -`; - -exports[`other jsx options should compile tsx file for with program 1`] = ` +exports[`other jsx options should compile tsx file 1`] = ` ===[ FILE: test-jsx-options.tsx ]=============================================== "use strict"; var App = function () { diff --git a/src/compiler/program.spec.ts b/src/compiler/program.spec.ts index f7854ba447..c29c981bc0 100644 --- a/src/compiler/program.spec.ts +++ b/src/compiler/program.spec.ts @@ -17,67 +17,18 @@ const baseTsJestConfig = { } describe('cache', () => { - const source = 'console.log("hello")' - - it('should use the cache with normal program', () => { - const fileName = 'test-cache-program.ts' - const tmp = tempDir('program-compiler') - writeFileSync(fileName, source, 'utf8') - const compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp }, - tsJestConfig: { - ...baseTsJestConfig, - incremental: false, - }, - }) - - logTarget.clear() - const compiled1 = compiler.compile(source, fileName) - expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(` - Array [ - "[level:20] readThrough(): cache miss - ", - "[level:20] updateMemoryCache(): update memory cache for program - ", - "[level:20] compileFn(): compiling using program - ", - "[level:20] visitSourceFileNode(): hoisting - ", - "[level:20] diagnoseFn(): computing diagnostics for test-cache-program.ts using program - ", - "[level:20] readThrough(): writing caches - ", - ] - `) - - logTarget.clear() - const compiled2 = compiler.compile(source, fileName) - expect(logTarget.lines).toMatchInlineSnapshot(` - Array [ - "[level:20] readThrough(): cache hit - ", - ] - `) - - expect(compiled2).toBe(compiled1) - - removeSync(fileName) - }) - - it('should use the cache with incremental program', () => { + it('should use the cache', () => { + const source = 'console.log("hello")' const fileName = 'test-cache-incremental-program.ts' const tmp = tempDir('incremental-program-compiler') writeFileSync(fileName, source, 'utf8') const compiler = makeCompiler({ jestConfig: { cache: true, cacheDirectory: tmp }, - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - }, + tsJestConfig: baseTsJestConfig, }) logTarget.clear() - const compiled1 = compiler.compile(source, fileName) + const compiled = compiler.compile(source, fileName) expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(` Array [ "[level:20] readThrough(): cache miss @@ -104,7 +55,7 @@ describe('cache', () => { ] `) - expect(compiled2).toBe(compiled1) + expect(compiled2).toBe(compiled) removeSync(fileName) }) @@ -115,155 +66,78 @@ describe('cache resolved modules for test file', () => { const fileName = 'src/__mocks__/main.spec.ts' const source = JSON.stringify(require('../__mocks__/main.spec')) - describe('with program', () => { - beforeEach(() => { - // tslint:disable-next-line:no-empty - spy = jest.spyOn(compilerUtils, 'cacheResolvedModules').mockImplementationOnce(() => {}) - }) - - afterEach(() => { - spy.mockRestore() - }) - - it('should cache resolved modules for test file with testMatchPatterns from jest config when match', () => { - const tmp = tempDir('compiler') - const compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(spec|test)\.[jt]sx?$/] as any[] }, - tsJestConfig: { tsConfig: false, compilerHost: true, incremental: false }, - }) - compiler.compile(source, fileName) - - expect(spy).toHaveBeenCalled() - expect(spy.mock.calls[0][0]).toEqual(normalize(fileName)) - expect(spy.mock.calls[0][1]).toEqual(source) - }) - - it(`shouldn't cache resolved modules for test file with testMatchPatterns from jest config when not match`, () => { - const tmp = tempDir('compiler') - const compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(foo|bar)\.[jt]sx?$/] as any[] }, - tsJestConfig: { tsConfig: false, compilerHost: true, incremental: false }, - }) - compiler.compile(source, fileName) - - expect(spy).not.toHaveBeenCalled() - }) + beforeEach(() => { + // tslint:disable-next-line:no-empty + spy = jest.spyOn(compilerUtils, 'cacheResolvedModules').mockImplementationOnce(() => {}) }) - describe('with incremental program', () => { - beforeEach(() => { - // tslint:disable-next-line:no-empty - spy = jest.spyOn(compilerUtils, 'cacheResolvedModules').mockImplementationOnce(() => {}) - }) + afterEach(() => { + spy.mockRestore() + }) - afterEach(() => { - spy.mockRestore() + it('should cache resolved modules for test file with testMatchPatterns from jest config when match', () => { + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(spec|test)\.[jt]sx?$/] as any[] }, + tsJestConfig: { tsConfig: false, compilerHost: true }, }) + compiler.compile(source, fileName) - it('should cache resolved modules for test file with testMatchPatterns from jest config when match', () => { - const tmp = tempDir('compiler') - const compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(spec|test)\.[jt]sx?$/] as any[] }, - tsJestConfig: { tsConfig: false, compilerHost: true, incremental: true }, - }) - compiler.compile(source, fileName) + expect(spy).toHaveBeenCalled() + expect(spy.mock.calls[0][0]).toEqual(normalize(fileName)) + expect(spy.mock.calls[0][1]).toEqual(source) + }) - expect(spy).toHaveBeenCalled() - expect(spy.mock.calls[0][0]).toEqual(normalize(fileName)) - expect(spy.mock.calls[0][1]).toEqual(source) + it(`shouldn't cache resolved modules for test file with testMatchPatterns from jest config when not match`, () => { + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(foo|bar)\.[jt]sx?$/] as any[] }, + tsJestConfig: { tsConfig: false, compilerHost: true }, }) + compiler.compile(source, fileName) - it(`shouldn't cache resolved modules for test file with testMatchPatterns from jest config when not match`, () => { - const tmp = tempDir('compiler') - const compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(foo|bar)\.[jt]sx?$/] as any[] }, - tsJestConfig: { tsConfig: false, compilerHost: true, incremental: true }, - }) - compiler.compile(source, fileName) - - expect(spy).not.toHaveBeenCalled() - }) + expect(spy).not.toHaveBeenCalled() }) }) -describe('allowJs', () => { +describe(`allowJs`, () => { const baseFileName = 'test-allowJs' const baseFileExt = 'test.js' const source = 'export default 42' const tsConfig = { allowJs: true } - describe(`with program`, () => { - it('should compile js file for allowJs true with outDir', () => { - const fileName = `${baseFileName}-program-outDir.${baseFileExt}` - writeFileSync(fileName, source, 'utf8') - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: false, - tsConfig: { - ...tsConfig, - outDir: '$$foo$$', - }, + it('should compile js file for allowJs true with outDir', () => { + const fileName = `${baseFileName}-incremental-outDir.${baseFileExt}` + writeFileSync(fileName, source, 'utf8') + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + tsConfig: { + ...tsConfig, + outDir: '$$foo$$', }, - }) - - const compiled = compiler.compile(source, fileName) - - expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() - - removeSync(fileName) + }, }) - it('should compile js file for allowJs true without outDir', () => { - const fileName = `${baseFileName}-program-no-outDir.${baseFileExt}` - writeFileSync(fileName, source, 'utf8') - const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig }, - }) - - const compiled = compiler.compile(source, fileName) + const compiled = compiler.compile(source, fileName) - expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() + expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() - removeSync(fileName) - }) + removeSync(fileName) }) - describe(`with incremental program`, () => { - it('should compile js file for allowJs true with outDir', () => { - const fileName = `${baseFileName}-incremental-outDir.${baseFileExt}` - writeFileSync(fileName, source, 'utf8') - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - tsConfig: { - ...tsConfig, - outDir: '$$foo$$', - }, - }, - }) - - const compiled = compiler.compile(source, fileName) - - expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() - - removeSync(fileName) + it('should compile js file for allowJs true without outDir', () => { + const fileName = `${baseFileName}-incremental-no-outDir.${baseFileExt}` + writeFileSync(fileName, source, 'utf8') + const compiler = makeCompiler({ + tsJestConfig: { ...baseTsJestConfig, tsConfig }, }) - it('should compile js file for allowJs true without outDir', () => { - const fileName = `${baseFileName}-incremental-no-outDir.${baseFileExt}` - writeFileSync(fileName, source, 'utf8') - const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig }, - }) - - const compiled = compiler.compile(source, fileName) + const compiled = compiler.compile(source, fileName) - expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() + expect(new ProcessedSource(compiled, fileName)).toMatchSnapshot() - removeSync(fileName) - }) + removeSync(fileName) }) }) @@ -286,19 +160,9 @@ describe('jsx preserve', () => { removeSync(fileName) }) - it('should compile tsx file 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 with incremental program', () => { + it('should compile tsx file', () => { const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig }, + tsJestConfig: { ...baseTsJestConfig, tsConfig }, }) const compiled = compiler.compile(source, fileName) @@ -326,19 +190,9 @@ describe('other jsx options', () => { removeSync(fileName) }) - it('should compile tsx file for 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 with incremental program', () => { + it('should compile tsx file', () => { const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig }, + tsJestConfig: { ...baseTsJestConfig, tsConfig }, }) const compiled = compiler.compile(source, fileName) @@ -362,64 +216,30 @@ const t: string = f(5) removeSync(fileName) }) - describe('normal program', () => { - it('should report diagnostics with pathRegex config matches file name', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: false, - diagnostics: { pathRegex: fileName }, - }, - }) - - expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot() + it('should report diagnostics with pathRegex config matches file name', () => { + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + diagnostics: { pathRegex: fileName }, + }, }) - it('should not report diagnostics with pathRegex config matches file name', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: false, - diagnostics: { pathRegex: 'foo.ts' }, - }, - }) - - try { - compiler.compile(source, fileName) - } catch (e) { - expect(e).not.toContain('TypeScript diagnostics') - } - }) + expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot() }) - describe('incremental program', () => { - it('should report diagnostics with pathRegex config matches file name', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - diagnostics: { pathRegex: fileName }, - }, - }) - - expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot() + it('should not report diagnostics with pathRegex config does not match file name', () => { + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + diagnostics: { pathRegex: 'foo.ts' }, + }, }) - it('should not report diagnostics with pathRegex config does not match file name', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - diagnostics: { pathRegex: 'foo.ts' }, - }, - }) - - try { - compiler.compile(source, fileName) - } catch (e) { - expect(e).not.toContain('TypeScript diagnostics') - } - }) + try { + compiler.compile(source, fileName) + } catch (e) { + expect(e).not.toContain('TypeScript diagnostics') + } }) }) @@ -435,28 +255,10 @@ describe('source-maps', () => { removeSync(fileName) }) - it('should have correct source maps with normal program', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: false, - }, - }) - - const compiled = compiler.compile(source, fileName) - - expect(new ProcessedSource(compiled, fileName).outputSourceMaps).toMatchObject({ - file: fileName, - sources: [fileName], - sourcesContent: [source], - }) - }) - - it('should have correct source maps with incremental program', () => { + it('should have correct source maps', () => { const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, - incremental: true, }, }) @@ -489,18 +291,9 @@ describe('cannot compile', () => { removeSync(fileName2) }) - it('should throw error with normal program', () => { - const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: false, tsConfig: false }, - }) - - expect(() => compiler.compile(source, fileName1)).toThrowErrorMatchingSnapshot() - expect(() => compiler.compile(source, fileName2)).toThrowErrorMatchingSnapshot() - }) - - it('should throw error with incremental program', () => { + it('should throw error', () => { const compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, incremental: true, tsConfig: false }, + tsJestConfig: { ...baseTsJestConfig, tsConfig: false }, }) expect(() => compiler.compile(source, fileName1)).toThrowErrorMatchingSnapshot() diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7df4c7e296..2c04286a55 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -28,8 +28,6 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa const ts = configs.compilerModule const cwd = configs.cwd const { options, projectReferences, errors } = configs.typescript - const incremental = configs.tsJest.incremental - const programDebugText = `${incremental ? 'incremental program' : 'program'}` const cacheDir = configs.tsCacheDir const compilerHostTraceCtx = { namespace: 'ts:compilerHost', @@ -49,47 +47,21 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa getNewLine: () => LINE_FEED, getCanonicalFileName: (fileName: string) => (ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase()), } - let builderProgram: _ts.EmitAndSemanticDiagnosticsBuilderProgram - let program: _ts.Program - let host: _ts.CompilerHost - if (incremental) { - host = ts.createIncrementalCompilerHost(options, sys) - builderProgram = ts.createIncrementalProgram({ - rootNames: Object.keys(memoryCache.versions), - options, - host, - configFileParsingDiagnostics: errors, - projectReferences, - }) - program = builderProgram.getProgram() - } else { - // Fallback for older TypeScript releases without incremental API. - host = { - ...sys, - getSourceFile: (fileName, languageVersion) => { - const contents = ts.sys.readFile(fileName) - - if (contents === undefined) return - - return ts.createSourceFile(fileName, contents, languageVersion) - }, - getDefaultLibFileName: () => ts.getDefaultLibFilePath(options), - useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, - } - program = ts.createProgram({ - rootNames: Object.keys(memoryCache.versions), - options, - host, - configFileParsingDiagnostics: errors, - projectReferences, - }) - } + const host: _ts.CompilerHost = ts.createIncrementalCompilerHost(options, sys) + let builderProgram: _ts.EmitAndSemanticDiagnosticsBuilderProgram = ts.createIncrementalProgram({ + rootNames: Object.keys(memoryCache.versions), + options, + host, + configFileParsingDiagnostics: errors, + projectReferences, + }) + let program = builderProgram.getProgram() // Read and cache custom transformers. const customTransformers = configs.tsCustomTransformers const updateMemoryCache = (contents: string, fileName: string): void => { - logger.debug({ fileName }, `updateMemoryCache(): update memory cache for ${programDebugText}`) + logger.debug({ fileName }, `updateMemoryCache(): update memory cache for incremental program`) - const sourceFile = incremental ? builderProgram.getSourceFile(fileName) : program.getSourceFile(fileName) + const sourceFile = builderProgram.getSourceFile(fileName) const fileVersion = memoryCache.versions[fileName] ?? 0 const isFileInCache = fileVersion !== 0 if (!isFileInCache) { @@ -114,15 +86,8 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa configFileParsingDiagnostics: errors, projectReferences, } - if (incremental) { - builderProgram = ts.createIncrementalProgram(programOptions) - program = builderProgram.getProgram() - } else { - program = ts.createProgram({ - ...programOptions, - oldProgram: program, - }) - } + builderProgram = ts.createIncrementalProgram(programOptions) + program = builderProgram.getProgram() } } @@ -132,35 +97,23 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa const output: [string, string] = ['', ''] // Must set memory cache before attempting to read file. updateMemoryCache(code, normalizedFileName) - const sourceFile = incremental - ? builderProgram.getSourceFile(normalizedFileName) - : program.getSourceFile(normalizedFileName) + const sourceFile = builderProgram.getSourceFile(normalizedFileName) if (!sourceFile) throw new TypeError(`Unable to read file: ${fileName}`) - logger.debug({ normalizedFileName }, `compileFn(): compiling using ${programDebugText}`) - - const result: _ts.EmitResult = incremental - ? builderProgram.emit( - sourceFile, - (path, file, _writeByteOrderMark) => { - output[path.endsWith('.map') ? 1 : 0] = file - }, - undefined, - undefined, - customTransformers, - ) - : program.emit( - sourceFile, - (path, file, _writeByteOrderMark) => { - output[path.endsWith('.map') ? 1 : 0] = file - }, - undefined, - undefined, - customTransformers, - ) + logger.debug({ normalizedFileName }, `compileFn(): compiling using incremental program`) + + const result: _ts.EmitResult = builderProgram.emit( + sourceFile, + (path, file, _writeByteOrderMark) => { + output[path.endsWith('.map') ? 1 : 0] = file + }, + undefined, + undefined, + customTransformers, + ) // Do type checking by getting TypeScript diagnostics - logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using ${programDebugText}`) + logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using incremental program`) doTypeChecking(configs, normalizedFileName, program, logger) /** @@ -185,7 +138,7 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa }) .forEach(entry => { logger.debug( - `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using ${programDebugText}`, + `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using incremental program`, ) doTypeChecking(configs, entry[0], program, logger) diff --git a/src/config/__snapshots__/config-set.spec.ts.snap b/src/config/__snapshots__/config-set.spec.ts.snap index fd10e56b38..3d2d14a6ec 100644 --- a/src/config/__snapshots__/config-set.spec.ts.snap +++ b/src/config/__snapshots__/config-set.spec.ts.snap @@ -52,7 +52,6 @@ Object { "pretty": true, "throws": true, }, - "incremental": true, "isolatedModules": false, "packageJson": Object { "kind": "file", @@ -142,7 +141,6 @@ Object { "pretty": true, "throws": true, }, - "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 d569576c12..c87713d46e 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -921,7 +921,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},\\"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}}"`, + `"{\\"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},\\"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 22d85ab50d..96c299af46 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -291,7 +291,6 @@ export class ConfigSet { const res: TsJestConfig = { tsConfig, compilerHost: options.compilerHost ?? false, - incremental: options.incremental ?? true, packageJson, babelConfig, diagnostics, diff --git a/src/types.ts b/src/types.ts index 437511054b..cb0df60049 100644 --- a/src/types.ts +++ b/src/types.ts @@ -57,12 +57,6 @@ export interface TsJestGlobalOptions { */ compilerHost?: boolean - /** - * Use TypeScript's Incremental Program. This option only works when `compilerHost` is `true` - * @default false - */ - incremental?: boolean - /** * Compiler to use (default to 'typescript'): */ @@ -155,7 +149,6 @@ export interface TsJestConfig { packageJson: TsJestConfig$packageJson isolatedModules: boolean compilerHost: boolean - incremental: boolean compiler: string diagnostics: TsJestConfig$diagnostics babelConfig: TsJestConfig$babelConfig