diff --git a/e2e/__cases__/compiler-host/main.spec.ts b/e2e/__cases__/compiler-host/main.spec.ts deleted file mode 100644 index 04bff66dc8..0000000000 --- a/e2e/__cases__/compiler-host/main.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { g } from './main' - -it('should pass', () => { - const x: string = g(5) - expect(x).toBe(5) -}) diff --git a/e2e/__cases__/compiler-host/main.ts b/e2e/__cases__/compiler-host/main.ts deleted file mode 100644 index 62b8101c36..0000000000 --- a/e2e/__cases__/compiler-host/main.ts +++ /dev/null @@ -1 +0,0 @@ -export const g = (v: number) => v diff --git a/e2e/__cases__/diagnostics/main.spec.ts b/e2e/__cases__/diagnostics/main.spec.ts index 4a6c38bbcd..4eb3db74e5 100644 --- a/e2e/__cases__/diagnostics/main.spec.ts +++ b/e2e/__cases__/diagnostics/main.spec.ts @@ -1,5 +1,11 @@ -import { strInNumOut } from './main' +import { Thing } from "./main"; -it('should pass', () => { - expect(strInNumOut('1')).toBe('1') -}) +export const thing: Thing = { a: 1 }; + +function doTheThing() { + return 1 + 2; +} + +it("should do the thing", () => { + expect(doTheThing()).toEqual(3); +}); diff --git a/e2e/__cases__/diagnostics/main.ts b/e2e/__cases__/diagnostics/main.ts index 56484de330..a4d045ad90 100644 --- a/e2e/__cases__/diagnostics/main.ts +++ b/e2e/__cases__/diagnostics/main.ts @@ -1,3 +1 @@ -export function strInNumOut(input: string): number { - return input -} +export type Thing = { a: number, b: number } diff --git a/e2e/__cases__/isolated-modules/main.spec.ts b/e2e/__cases__/isolated-modules/main.spec.ts new file mode 100644 index 0000000000..d1b342a18a --- /dev/null +++ b/e2e/__cases__/isolated-modules/main.spec.ts @@ -0,0 +1,11 @@ +import { Thing } from "./main"; + +// See the Thing definition. Changing the type definition should result in a compile failure here. +export const thing: Thing = { a: 1 }; +function doTheThing() { + return 1 + 2; +} + +it("should do the thing", () => { + expect(doTheThing()).toEqual(3); +}); diff --git a/e2e/__cases__/isolated-modules/main.ts b/e2e/__cases__/isolated-modules/main.ts new file mode 100644 index 0000000000..a4d045ad90 --- /dev/null +++ b/e2e/__cases__/isolated-modules/main.ts @@ -0,0 +1 @@ +export type Thing = { a: number, b: number } diff --git a/e2e/__helpers__/templates.ts b/e2e/__helpers__/templates.ts index ff20228f6b..30560cff53 100644 --- a/e2e/__helpers__/templates.ts +++ b/e2e/__helpers__/templates.ts @@ -6,7 +6,7 @@ export enum PackageSets { // invalid unsupportedVersion = 'with-unsupported-version', } -export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7], - allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7], - allPackageSetsWithProgram = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig], - allPackageSetsWithoutProgram = [PackageSets.typescript2_7, PackageSets.unsupportedVersion] +export const allValidPackageSets = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7] +export const allPackageSetsWithPreset = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig, PackageSets.typescript2_7] +export const allPackageSetsWithProgram = [PackageSets.default, PackageSets.babel7, PackageSets.babel7StringConfig] +export const allPackageSetsWithoutProgram = [PackageSets.typescript2_7, PackageSets.unsupportedVersion] diff --git a/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap b/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap deleted file mode 100644 index 1f5899ccb8..0000000000 --- a/e2e/__tests__/__snapshots__/compiler-host.test.ts.snap +++ /dev/null @@ -1,213 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`With compilerHost enabled and incremental disabled should fail using template "with-typescript-2-7" 1`] = ` - × jest --no-cache - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - ● Test suite failed to run - - TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined - - at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51) - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental disabled should fail using template "with-unsupported-version" 1`] = ` - × jest --no-cache - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. - FAIL ./main.spec.ts - ● Test suite failed to run - - TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined - - at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51) - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental disabled should pass using template "default" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental disabled should pass using template "with-babel-7-string-config" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental enabled should fail using template "with-typescript-2-7" 1`] = ` - × jest --no-cache - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - FAIL ./main.spec.ts - ● Test suite failed to run - - TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined - - at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51) - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental enabled should fail using template "with-unsupported-version" 1`] = ` - × jest --no-cache - ↳ exit code: 1 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. - FAIL ./main.spec.ts - ● Test suite failed to run - - TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined - - at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51) - - Test Suites: 1 failed, 1 total - Tests: 0 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental enabled should pass using template "default" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`With compilerHost enabled and incremental enabled should pass using template "with-babel-7-string-config" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.spec.ts:4:9 - error TS2322: Type 'number' is not assignable to type 'string'. - - 4 const x: string = g(5) - ~ - PASS ./main.spec.ts - √ should pass - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; diff --git a/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap b/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap index 1d81a46716..aba886485f 100644 --- a/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap +++ b/e2e/__tests__/__snapshots__/diagnostics.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`With diagnostics, first throws should fail using template "default" 1`] = ` +exports[`With diagnostics throw using incremental program first throw should fail using template "default" 1`] = ` × jest ↳ exit code: 1 ===[ STDOUT ]=================================================================== @@ -9,10 +9,42 @@ exports[`With diagnostics, first throws should fail using template "default" 1`] FAIL ./main.spec.ts ● Test suite failed to run - main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + main.spec.ts:3:14 - error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'. - 2 return input - ~~~~~~~~~~~~ + 3 export const thing: Thing = { a: 1 }; + ~~~~~ + + main.ts:1:34 + 1 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 incremental 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. Test Suites: 1 failed, 1 total Tests: 0 total @@ -22,7 +54,7 @@ exports[`With diagnostics, first throws should fail using template "default" 1`] ================================================================================ `; -exports[`With diagnostics, first throws should fail using template "with-babel-7" 1`] = ` +exports[`With diagnostics throw using incremental program first throw should fail using template "with-babel-7-string-config" 1`] = ` × jest ↳ exit code: 1 ===[ STDOUT ]=================================================================== @@ -31,10 +63,15 @@ exports[`With diagnostics, first throws should fail using template "with-babel-7 FAIL ./main.spec.ts ● Test suite failed to run - main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + main.spec.ts:3:14 - error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'. - 2 return input - ~~~~~~~~~~~~ + 3 export const thing: Thing = { a: 1 }; + ~~~~~ + + main.ts:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. Test Suites: 1 failed, 1 total Tests: 0 total @@ -44,7 +81,58 @@ exports[`With diagnostics, first throws should fail using template "with-babel-7 ================================================================================ `; -exports[`With diagnostics, first throws should fail using template "with-babel-7-string-config" 1`] = ` +exports[`With diagnostics throw using incremental program then passed when content 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 + √ should do the thing + + 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 incremental program then passed when content 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 + √ should do the thing + + 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 incremental program then passed when content 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 + √ should do the thing + + 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 incremental program with unsupported version should fail using template "with-typescript-2-7" 1`] = ` × jest ↳ exit code: 1 ===[ STDOUT ]=================================================================== @@ -53,10 +141,9 @@ exports[`With diagnostics, first throws should fail using template "with-babel-7 FAIL ./main.spec.ts ● Test suite failed to run - main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + TypeError: ts.createIncrementalCompilerHost is not a function - 2 return input - ~~~~~~~~~~~~ + at Object.exports.compileUsingProgram (../../__templates__/with-typescript-2-7/node_modules/ts-jest/dist/compiler/program.js:47:19) Test Suites: 1 failed, 1 total Tests: 0 total @@ -66,19 +153,19 @@ exports[`With diagnostics, first throws should fail using template "with-babel-7 ================================================================================ `; -exports[`With diagnostics, first throws should fail using template "with-typescript-2-7" 1`] = ` +exports[`With diagnostics throw using incremental program with unsupported version should fail using template "with-unsupported-version" 1`] = ` × jest ↳ exit code: 1 ===[ STDOUT ]=================================================================== ===[ STDERR ]=================================================================== + ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. FAIL ./main.spec.ts ● Test suite failed to run - main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + TypeError: ts.createIncrementalCompilerHost is not a function - 2 return input - ~~~~~~~~~~~~ + at Object.exports.compileUsingProgram (../../__templates__/with-unsupported-version/node_modules/ts-jest/dist/compiler/program.js:47:19) Test Suites: 1 failed, 1 total Tests: 0 total @@ -88,18 +175,118 @@ exports[`With diagnostics, first throws should fail using template "with-typescr ================================================================================ `; -exports[`With diagnostics, warn only should pass using template "default" 1`] = ` - √ jest --no-cache - ↳ exit code: 0 +exports[`With diagnostics throw using language service 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:1:34 + 1 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 language service 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:1:34 + 1 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 language service 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:1:34 + 1 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 language service first throw should fail using template "with-typescript-2-7" 1`] = ` + × jest + ↳ exit code: 1 ===[ STDOUT ]=================================================================== ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + FAIL ./main.spec.ts + ● Test suite failed to run + + main.spec.ts:3:14 - error TS2322: Type '{ a: number; }' is not assignable to type 'Thing'. + Property 'b' is missing in type '{ a: number; }'. + + 3 export const thing: Thing = { a: 1 }; + ~~~~~ + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics throw using language service then passed when content has changed to valid base on cache of the previous run should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== - 2 return input - ~~~~~~~~~~~~ + ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -109,18 +296,31 @@ exports[`With diagnostics, warn only should pass using template "default" 1`] = ================================================================================ `; -exports[`With diagnostics, warn only should pass using template "with-babel-7" 1`] = ` - √ jest --no-cache +exports[`With diagnostics throw using language service then passed when content 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 ]=================================================================== - ts-jest[ts-compiler] (WARN) main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + PASS ./main.spec.ts + √ should do the thing + + 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 language service then passed when content 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 ]=================================================================== - 2 return input - ~~~~~~~~~~~~ + ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -130,18 +330,112 @@ exports[`With diagnostics, warn only should pass using template "with-babel-7" 1 ================================================================================ `; -exports[`With diagnostics, warn only should pass using template "with-babel-7-string-config" 1`] = ` - √ jest --no-cache +exports[`With diagnostics throw using language service then passed when content has changed to valid base on cache of the previous run should pass using template "with-typescript-2-7" 1`] = ` + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ===[ STDERR ]=================================================================== - ts-jest[ts-compiler] (WARN) main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + PASS ./main.spec.ts + √ should do the thing + + 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 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:1:34 + 1 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:1:34 + 1 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'. - 2 return input - ~~~~~~~~~~~~ + 3 export const thing: Thing = { a: 1 }; + ~~~~~ + + main.ts:1:34 + 1 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 passed when content 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 - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -151,18 +445,31 @@ exports[`With diagnostics, warn only should pass using template "with-babel-7-st ================================================================================ `; -exports[`With diagnostics, warn only should pass using template "with-typescript-2-7" 1`] = ` - √ jest --no-cache +exports[`With diagnostics throw using program then passed when content 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 ]=================================================================== - ts-jest[ts-compiler] (WARN) main.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'. + PASS ./main.spec.ts + √ should do the thing + + 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 passed when content 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 ]=================================================================== - 2 return input - ~~~~~~~~~~~~ + ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -171,3 +478,558 @@ exports[`With diagnostics, warn only should pass using template "with-typescript Ran all test suites. ================================================================================ `; + +exports[`With diagnostics throw using program with unsupported version should fail using template "with-typescript-2-7" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined + + at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics throw using program with unsupported version should fail using template "with-unsupported-version" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined + + at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics warn only using incremental program first show warning should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using incremental program first show warning should pass using template "with-babel-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using incremental program first show warning should pass using template "with-babel-7-string-config" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using incremental program then not showing warning when content 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 + √ should do the thing + + 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 using incremental program then not showing warning when content 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 + √ should do the thing + + 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 using incremental program then not showing warning when content 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 + √ should do the thing + + 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 using incremental program with unsupported version should fail using template "with-typescript-2-7" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: ts.createIncrementalCompilerHost is not a function + + at Object.exports.compileUsingProgram (../../__templates__/with-typescript-2-7/node_modules/ts-jest/dist/compiler/program.js:47:19) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics warn only using incremental program with unsupported version should fail using template "with-unsupported-version" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: ts.createIncrementalCompilerHost is not a function + + at Object.exports.compileUsingProgram (../../__templates__/with-unsupported-version/node_modules/ts-jest/dist/compiler/program.js:47:19) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics warn only using language service first show warning should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using language service first show warning should pass using template "with-babel-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using language service first show warning should pass using template "with-babel-7-string-config" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using language service first show warning should pass using template "with-typescript-2-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) main.spec.ts:3:14 - error TS2322: Type '{ a: number; }' is not assignable to type 'Thing'. + Property 'b' is missing in type '{ a: number; }'. + + 3 export const thing: Thing = { a: 1 }; + ~~~~~ + PASS ./main.spec.ts + √ should do the thing + + 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 using language service then not showing warning when content 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 + √ should do the thing + + 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 using language service then not showing warning when content 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 + √ should do the thing + + 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 using language service then not showing warning when content 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 + √ should do the thing + + 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 using language service then not showing warning when content has changed to valid base on cache of the previous run should pass using template "with-typescript-2-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./main.spec.ts + √ should do the thing + + 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 using program first show warning should pass using template "default" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using program first show warning should pass using template "with-babel-7" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using program first show warning should pass using template "with-babel-7-string-config" 1`] = ` + √ jest + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[ts-compiler] (WARN) 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:1:34 + 1 export type Thing = { a: number, b: number } + ~ + 'b' is declared here. + PASS ./main.spec.ts + √ should do the thing + + 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 using program then not show warning when content 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 + √ should do the thing + + 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 using program then not show warning when content 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 + √ should do the thing + + 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 using program then not show warning when content 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 + √ should do the thing + + 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 using program with unsupported version should fail using template "with-typescript-2-7" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined + + at Object.createProgram (../../__templates__/with-typescript-2-7/node_modules/typescript/lib/typescript.js:73929:51) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`With diagnostics warn only using program with unsupported version should fail using template "with-unsupported-version" 1`] = ` + × jest + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. + FAIL ./main.spec.ts + ● Test suite failed to run + + TypeError: Cannot read property 'maxNodeModuleJsDepth' of undefined + + at Object.createProgram (../../__templates__/with-unsupported-version/node_modules/typescript/lib/typescript.js:69709:51) + + Test Suites: 1 failed, 1 total + Tests: 0 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/__snapshots__/isolated-modules.test.ts.snap b/e2e/__tests__/__snapshots__/isolated-modules.test.ts.snap index 26b6a3e2c1..2a39f6fafc 100644 --- a/e2e/__tests__/__snapshots__/isolated-modules.test.ts.snap +++ b/e2e/__tests__/__snapshots__/isolated-modules.test.ts.snap @@ -7,7 +7,7 @@ exports[`With isolatedModules enabled should pass using template "default" 1`] = ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -24,7 +24,7 @@ exports[`With isolatedModules enabled should pass using template "with-babel-7" ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -41,7 +41,7 @@ exports[`With isolatedModules enabled should pass using template "with-babel-7-s ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total @@ -58,7 +58,7 @@ exports[`With isolatedModules enabled should pass using template "with-typescrip ===[ STDERR ]=================================================================== PASS ./main.spec.ts - √ should pass + √ should do the thing Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total diff --git a/e2e/__tests__/__snapshots__/logger.test.ts.snap b/e2e/__tests__/__snapshots__/logger.test.ts.snap index 1bc7b07701..9956fddb97 100644 --- a/e2e/__tests__/__snapshots__/logger.test.ts.snap +++ b/e2e/__tests__/__snapshots__/logger.test.ts.snap @@ -12,30 +12,28 @@ Array [ "[level:20] backporting config", "[level:20] normalized jest config", "[level:20] normalized ts-jest config", + "[level:20] babel is disabled", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] readTsConfig(): reading /tsconfig.json", "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", "[level:20] file caching disabled", "[level:20] compileUsingLanguageService(): create typescript compiler", "[level:20] compileUsingLanguageService(): creating language service", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", - "[level:20] babel is disabled", - "[level:20] processing /Hello.spec.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.spec.ts using language service", "[level:20] computing cache key for /Hello.ts", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", "[level:20] processing /Hello.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.ts using language service", ] `; @@ -51,35 +49,33 @@ Array [ "[level:20] backporting config", "[level:20] normalized jest config", "[level:20] normalized ts-jest config", + "[level:20] normalized babel config via ts-jest option", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] readTsConfig(): reading /tsconfig.json", "[level:20] normalized typescript config", - "[level:20] file caching disabled", - "[level:20] compileUsingLanguageService(): create typescript compiler", - "[level:20] compileUsingLanguageService(): creating language service", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", - "[level:20] normalized babel config via ts-jest option", "[level:20] processing /Hello.spec.ts", "[level:20] creating babel-jest transformer", "[level:20] loaded module babel-jest", "[level:20] patching babel-jest", "[level:20] checking version of babel-jest: OK", + "[level:20] file caching disabled", + "[level:20] compileUsingLanguageService(): create typescript compiler", + "[level:20] compileUsingLanguageService(): creating language service", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.spec.ts using language service", "[level:20] calling babel-jest processor", "[level:20] computing cache key for /Hello.ts", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", "[level:20] processing /Hello.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.ts using language service", "[level:20] calling babel-jest processor", ] `; @@ -97,35 +93,33 @@ Array [ "[level:20] normalized jest config", "[level:20] resolved path from babel.config.js to /babel.config.js", "[level:20] normalized ts-jest config", + "[level:20] normalized babel config via ts-jest option", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] readTsConfig(): reading /tsconfig.json", "[level:20] normalized typescript config", - "[level:20] file caching disabled", - "[level:20] compileUsingLanguageService(): create typescript compiler", - "[level:20] compileUsingLanguageService(): creating language service", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", - "[level:20] normalized babel config via ts-jest option", "[level:20] processing /Hello.spec.ts", "[level:20] creating babel-jest transformer", "[level:20] loaded module babel-jest", "[level:20] patching babel-jest", "[level:20] checking version of babel-jest: OK", + "[level:20] file caching disabled", + "[level:20] compileUsingLanguageService(): create typescript compiler", + "[level:20] compileUsingLanguageService(): creating language service", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.spec.ts using language service", "[level:20] calling babel-jest processor", "[level:20] computing cache key for /Hello.ts", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", "[level:20] processing /Hello.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.ts using language service", "[level:20] calling babel-jest processor", ] `; @@ -142,30 +136,28 @@ Array [ "[level:20] backporting config", "[level:20] normalized jest config", "[level:20] normalized ts-jest config", + "[level:20] babel is disabled", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] readTsConfig(): reading /tsconfig.json", "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", "[level:20] file caching disabled", "[level:20] compileUsingLanguageService(): create typescript compiler", "[level:20] compileUsingLanguageService(): creating language service", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", - "[level:20] babel is disabled", - "[level:20] processing /Hello.spec.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.spec.ts using language service", "[level:20] computing cache key for /Hello.ts", - "[level:20] updateMemoryCache(): update memory cache for language service", - "[level:20] compileFn(): computing diagnostics for language service", "[level:20] processing /Hello.ts", "[level:20] readThrough(): no cache", "[level:20] compileFn(): compiling using language service", "[level:20] updateMemoryCache(): update memory cache for language service", "[level:20] visitSourceFileNode(): hoisting", + "[level:20] diagnoseFn(): computing diagnostics for /Hello.ts using language service", ] `; diff --git a/e2e/__tests__/compiler-host.test.ts b/e2e/__tests__/compiler-host.test.ts deleted file mode 100644 index 21625f4b8d..0000000000 --- a/e2e/__tests__/compiler-host.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { allPackageSetsWithProgram, allPackageSetsWithoutProgram } from '../__helpers__/templates' -import { configureTestCase } from '../__helpers__/test-case' - -describe('With compilerHost enabled and incremental disabled', () => { - const testCase = configureTestCase('compiler-host', { - tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } }, - noCache: true, - }) - - testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => { - it(testLabel, () => { - // tslint:disable-next-line:no-console - console.log = jest.fn() - const result = runTest() - expect(result.status).toBe(0) - expect(result).toMatchSnapshot() - }) - }) - - testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(1) - expect(result).toMatchSnapshot() - }) - }) -}) - -describe('With compilerHost enabled and incremental enabled', () => { - const testCase = configureTestCase('compiler-host', { - tsJestConfig: { compilerHost: true, incremental: false, diagnostics: { warnOnly: true } }, - noCache: true, - }) - - testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => { - it(testLabel, () => { - // tslint:disable-next-line:no-console - console.log = jest.fn() - const result = runTest() - expect(result.status).toBe(0) - expect(result).toMatchSnapshot() - }) - }) - - testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(1) - expect(result).toMatchSnapshot() - }) - }) -}) diff --git a/e2e/__tests__/diagnostics.test.ts b/e2e/__tests__/diagnostics.test.ts index a118b33e6a..5d88887fc4 100644 --- a/e2e/__tests__/diagnostics.test.ts +++ b/e2e/__tests__/diagnostics.test.ts @@ -1,29 +1,285 @@ -import { allValidPackageSets } from '../__helpers__/templates' +import { writeFileSync } from 'fs' +import { join } from 'path' + +import { allPackageSetsWithProgram, allPackageSetsWithoutProgram, allValidPackageSets } from '../__helpers__/templates' import { configureTestCase } from '../__helpers__/test-case' -describe('With diagnostics, first throws', () => { - const testCase = configureTestCase('diagnostics') +describe('With diagnostics throw', () => { + describe('using language service', () => { + const testCase = configureTestCase('diagnostics') + + describe('first throw', () => { + testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('then passed when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { a: number, b: number }\n`) + }) + + testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + }) + + describe('using program', () => { + const testCase = configureTestCase('diagnostics', { + 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 passed when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export 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('with unsupported version', () => { + testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) + }) + }) + + describe('using incremental program', () => { + const testCase = configureTestCase('diagnostics', { + tsJestConfig: { + compilerHost: true, + incremental: true, + }, + }) + + describe('first throw', () => { + testCase.runWithTemplates(allPackageSetsWithProgram, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('then passed when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export 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() + }) + }) + }) - testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(1) - expect(result).toMatchSnapshot() + describe('with unsupported version', () => { + testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) }) }) }) -describe('With diagnostics, warn only', () => { - const testCase = configureTestCase('diagnostics', { - tsJestConfig: { diagnostics: { warnOnly: true } }, - noCache: true, // warnings shown only on first compilation +describe('With diagnostics warn only', () => { + describe('using language service', () => { + const testCase = configureTestCase('diagnostics', { + tsJestConfig: { + diagnostics: { warnOnly: true }, + }, + }) + + describe('first show warning', () => { + testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('then not showing warning when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { a: number, b: number }\n`) + }) + + testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + }) + + describe('using program', () => { + const testCase = configureTestCase('diagnostics', { + tsJestConfig: { + compilerHost: true, + incremental: false, + diagnostics: { warnOnly: true }, + }, + }) + + describe('first show warning', () => { + testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('then not show warning when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export 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('with unsupported version', () => { + testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) + }) }) - testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => { - it(testLabel, () => { - const result = runTest() - expect(result.status).toBe(0) - expect(result).toMatchSnapshot() + describe('using incremental program', () => { + const testCase = configureTestCase('diagnostics', { + tsJestConfig: { + compilerHost: true, + incremental: true, + diagnostics: { warnOnly: true }, + }, + }) + + describe('first show warning', () => { + testCase.runWithTemplates(allPackageSetsWithProgram, 0, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(0) + expect(result).toMatchSnapshot() + }) + }) + }) + + describe('then not showing warning when content has changed to valid base on cache of the previous run', () => { + beforeAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export type Thing = { + a: number; + // b: number; +}`) + }) + + afterAll(() => { + writeFileSync(join(__dirname, '../__cases__/diagnostics/main.ts'), `export 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('with unsupported version', () => { + testCase.runWithTemplates(allPackageSetsWithoutProgram, 1, (runTest, { testLabel }) => { + it(testLabel, () => { + const result = runTest() + expect(result.status).toBe(1) + expect(result).toMatchSnapshot() + }) + }) }) }) }) diff --git a/e2e/__tests__/isolated-modules.test.ts b/e2e/__tests__/isolated-modules.test.ts index 0f1eb31251..0bda1cc770 100644 --- a/e2e/__tests__/isolated-modules.test.ts +++ b/e2e/__tests__/isolated-modules.test.ts @@ -2,7 +2,7 @@ import { allValidPackageSets } from '../__helpers__/templates' import { configureTestCase } from '../__helpers__/test-case' describe('With isolatedModules enabled', () => { - const testCase = configureTestCase('diagnostics', { + const testCase = configureTestCase('isolated-modules', { tsJestConfig: { isolatedModules: true }, }) diff --git a/jest.config.js b/jest.config.js index 9b6a9ccd93..fea7bdb9e6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,6 +5,7 @@ module.exports = { '\\.ts$': '/dist/index.js', }, testMatch: ['/src/**/*.spec.ts'], + testPathIgnorePatterns: ['/src/__mocks__/*'], collectCoverageFrom: [ '/src/**/*.ts', '!/src/**/*.d.ts', diff --git a/package-lock.json b/package-lock.json index 95a10763ca..3e90859906 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1289,6 +1289,12 @@ } } }, + "@types/braces": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.0.tgz", + "integrity": "sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw==", + "dev": true + }, "@types/buffer-from": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/buffer-from/-/buffer-from-1.1.0.tgz", @@ -1402,6 +1408,15 @@ "@types/lodash": "*" } }, + "@types/micromatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.1.tgz", + "integrity": "sha512-my6fLBvpY70KattTNzYOK6KU1oR1+UCz9ug/JbcF5UrEmeCt9P7DV2t7L8+t18mMPINqGQCE4O8PLOPbI84gxw==", + "dev": true, + "requires": { + "@types/braces": "*" + } + }, "@types/mkdirp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.0.tgz", @@ -1921,7 +1936,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -3523,7 +3537,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -4586,8 +4599,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-obj": { "version": "1.0.1", @@ -7073,7 +7085,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.0.5" @@ -7595,8 +7606,7 @@ "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", - "dev": true + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==" }, "pidtree": { "version": "0.3.1", @@ -9046,7 +9056,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } diff --git a/package.json b/package.json index 544ab43b68..8be9c64f08 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", + "micromatch": "4.x", "mkdirp": "1.x", "resolve": "1.x", "semver": "6.x", @@ -97,9 +98,10 @@ "@types/lodash.memoize": "4.x", "@types/lodash.merge": "4.x", "@types/lodash.set": "4.x", + "@types/micromatch": "4.x", "@types/mkdirp": "latest", "@types/node": "10.x", - "@types/react": "^16.x", + "@types/react": "16.x", "@types/resolve": "latest", "@types/semver": "latest", "@types/yargs": "latest", diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts index d5ec454953..fcac848db3 100644 --- a/src/__helpers__/fakers.ts +++ b/src/__helpers__/fakers.ts @@ -69,6 +69,7 @@ export function makeCompiler({ ...(tsJestConfig.diagnostics as any), pretty: false, } + jestConfig = { ...jestConfig, testMatch: ['^.+\\.tsx?$'], testRegex: ['^.+\\.[tj]sx?$'] } const cs = new ConfigSet(getJestConfig(jestConfig, tsJestConfig), parentConfig) return createCompiler(cs) diff --git a/src/__mocks__/main.spec.ts b/src/__mocks__/main.spec.ts new file mode 100644 index 0000000000..40e5da46d6 --- /dev/null +++ b/src/__mocks__/main.spec.ts @@ -0,0 +1,3 @@ +import { Thing } from './main' + +export const thing: Thing = { a: 1 } diff --git a/src/__mocks__/main.ts b/src/__mocks__/main.ts new file mode 100644 index 0000000000..fea8e002b1 --- /dev/null +++ b/src/__mocks__/main.ts @@ -0,0 +1,3 @@ +export interface Thing { + a: number +} diff --git a/src/__mocks__/thing.spec.ts b/src/__mocks__/thing.spec.ts new file mode 100644 index 0000000000..bc40cfb36e --- /dev/null +++ b/src/__mocks__/thing.spec.ts @@ -0,0 +1,5 @@ +interface Thing { + a: number +} + +export const thing: Thing = { a: 1 } diff --git a/src/compiler/__snapshots__/program.spec.ts.snap b/src/compiler/__snapshots__/program.spec.ts.snap index ff4913cad6..b566e22448 100644 --- a/src/compiler/__snapshots__/program.spec.ts.snap +++ b/src/compiler/__snapshots__/program.spec.ts.snap @@ -50,6 +50,10 @@ This is usually the result of a faulty configuration or import. Make sure there 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"; @@ -145,7 +149,3 @@ exports[`other jsx options should compile tsx file for with program 1`] = ` version: 3 ================================================================================ `; - -exports[`typings 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[`typings 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'."`; diff --git a/src/compiler/compiler-utils.spec.ts b/src/compiler/compiler-utils.spec.ts new file mode 100644 index 0000000000..7066393a30 --- /dev/null +++ b/src/compiler/compiler-utils.spec.ts @@ -0,0 +1,74 @@ +import { logger } from 'bs-logger' +import * as fs from 'fs' +import { resolve } from 'path' + +import { makeCompiler } from '../__helpers__/fakers' +import { logTargetMock } from '../__helpers__/mocks' +import { tempDir } from '../__helpers__/path' +import { MemoryCache } from '../types' + +import { cacheResolvedModules, getResolvedModulesCache } from './compiler-utils' + +const memoryCache: MemoryCache = { + contents: Object.create(null), + versions: Object.create(null), + outputs: Object.create(null), + resolvedModules: Object.create(null), +} + +const logTarget = logTargetMock() + +describe('cacheResolvedModules', () => { + let spy: jest.SpyInstance + + beforeAll(() => { + // tslint:disable-next-line:no-empty + spy = jest.spyOn(fs, 'writeFileSync') + }) + + beforeEach(() => { + memoryCache.resolvedModules = Object.create(null) + }) + + afterEach(() => { + spy.mockClear() + spy.mockReset() + spy.mockRestore() + }) + + it('should store resolved modules in memory cache and file system when there are resolved modules', () => { + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, + tsJestConfig: { tsConfig: false }, + }) + const fileName = 'src/__mocks__/main.spec.ts' + const source = JSON.stringify(require('../__mocks__/main.spec')) + + compiler.compile(source, fileName) + + logTarget.clear() + cacheResolvedModules(fileName, memoryCache, compiler.program!, tmp, logger) + + expect(memoryCache.resolvedModules[fileName]).toContain(resolve('src/__mocks__/main.ts')) + expect(spy).toHaveBeenCalledWith(getResolvedModulesCache(tmp), JSON.stringify(memoryCache.resolvedModules)) + }) + + it(`should store resolved modules in memory cache but not file system when there aren't resolved modules`, () => { + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, + tsJestConfig: { tsConfig: false }, + }) + const fileName = 'src/__mocks__/thing.spec.ts' + const source = JSON.stringify(require('../__mocks__/thing.spec')) + + compiler.compile(source, fileName) + + logTarget.clear() + cacheResolvedModules(fileName, memoryCache, compiler.program!, tmp, logger) + + expect(memoryCache.resolvedModules[fileName]).toBe(undefined) + expect(spy).not.toHaveBeenCalled() + }) +}) diff --git a/src/compiler/compiler-utils.ts b/src/compiler/compiler-utils.ts new file mode 100644 index 0000000000..7bb3b19195 --- /dev/null +++ b/src/compiler/compiler-utils.ts @@ -0,0 +1,50 @@ +import { Logger } from 'bs-logger' +import { writeFileSync } from 'fs' +import { join, normalize } from 'path' +import * as _ts from 'typescript' + +import { MemoryCache } from '../types' +import { sha1 } from '../util/sha1' + +/** + * @internal + */ +export const hasOwn = Object.prototype.hasOwnProperty +/** + * @internal + */ +export function getResolvedModulesCache(cachedir: string): string { + return join(cachedir, sha1('ts-jest-resolved-modules', '\x00')) +} + +/** + * @internal + * Get resolved modules of a test file and put into memory cache + */ +export function cacheResolvedModules( + fileName: string, + memoryCache: MemoryCache, + program: _ts.Program, + cacheDir: string, + logger: Logger, +) { + // @ts-ignore + const importReferences = program.getSourceFile(fileName)!.imports + /** + * Ugly trick while waiting for https://github.com/microsoft/TypeScript/issues/33994 + */ + if (importReferences.length) { + logger.debug({ fileName }, `cacheResolvedModules(): get resolved modules of test file ${fileName}`) + + memoryCache.resolvedModules[fileName] = importReferences + .filter((importReference: any) => importReference.parent.parent.resolvedModules?.get(importReference.text)) + .map((importReference: any) => { + return normalize( + (importReference.parent.parent.resolvedModules.get(importReference.text) as _ts.ResolvedModule) + .resolvedFileName, + ) + }) + .reduce((a: any, b: any) => a.concat(b), []) + writeFileSync(getResolvedModulesCache(cacheDir), JSON.stringify(memoryCache.resolvedModules)) + } +} diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index 20cf839946..b991e97fb2 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -38,6 +38,7 @@ import { ConfigSet } from '../config/config-set' import { CompileFn, CompilerInstance, MemoryCache, TsCompiler } from '../types' import { sha1 } from '../util/sha1' +import { getResolvedModulesCache } from './compiler-utils' import { compileUsingLanguageService } from './language-service' import { compileUsingProgram } from './program' import { compileUsingTranspileModule } from './transpile-module' @@ -100,7 +101,9 @@ const readThrough = ( if (!cachedir) { return (code: string, fileName: string, lineOffset?: number) => { const normalizedFileName = normalize(fileName) + logger.debug({ normalizedFileName }, 'readThrough(): no cache') + const [value, sourceMap] = compileFn(code, normalizedFileName, lineOffset) const output = updateOutput(value, fileName, sourceMap, getExtension) memoryCache.outputs[normalizedFileName] = output @@ -111,12 +114,17 @@ const readThrough = ( // Make sure the cache directory exists before continuing. mkdirp.sync(cachedir) + try { + const resolvedModulesCache = readFileSync(getResolvedModulesCache(cachedir), 'utf-8') + /* istanbul ignore next (covered by e2e) */ + memoryCache.resolvedModules = JSON.parse(resolvedModulesCache) + } catch (e) {} return (code: string, fileName: string, lineOffset?: number) => { - const normalizedFileName = normalize(fileName), - cachePath = join(cachedir, getCacheName(code, normalizedFileName)), - extension = getExtension(normalizedFileName), - outputPath = `${cachePath}${extension}` + const normalizedFileName = normalize(fileName) + const cachePath = join(cachedir, getCacheName(code, normalizedFileName)) + const extension = getExtension(normalizedFileName) + const outputPath = `${cachePath}${extension}` try { const output = readFileSync(outputPath, 'utf8') if (isValidCacheContent(output)) { @@ -129,8 +137,8 @@ const readThrough = ( logger.debug({ fileName }, 'readThrough(): cache miss') - const [value, sourceMap] = compileFn(code, normalizedFileName, lineOffset), - output = updateOutput(value, normalizedFileName, sourceMap, getExtension) + const [value, sourceMap] = compileFn(code, normalizedFileName, lineOffset) + const output = updateOutput(value, normalizedFileName, sourceMap, getExtension) logger.debug({ normalizedFileName, outputPath }, 'readThrough(): writing caches') @@ -151,14 +159,15 @@ export const createCompiler = (configs: ConfigSet): TsCompiler => { typescript: { options: compilerOptions, fileNames }, tsJest, } = configs - const cachedir = configs.tsCacheDir, - ts = configs.compilerModule, // Require the TypeScript compiler and configuration. - extensions = ['.ts', '.tsx'], - memoryCache: MemoryCache = { - contents: Object.create(null), - versions: Object.create(null), - outputs: Object.create(null), - } + const cachedir = configs.tsCacheDir + const ts = configs.compilerModule // Require the TypeScript compiler and configuration. + const extensions = ['.ts', '.tsx'] + const memoryCache: MemoryCache = { + contents: Object.create(null), + versions: Object.create(null), + outputs: Object.create(null), + resolvedModules: Object.create(null), + } // Enable `allowJs` when flag is set. if (compilerOptions.allowJs) { extensions.push('.js') @@ -184,5 +193,5 @@ export const createCompiler = (configs: ConfigSet): TsCompiler => { } const compile = readThrough(cachedir, memoryCache, compilerInstance.compileFn, getExtension, logger) - return { cwd: configs.cwd, compile, program: compilerInstance.program, diagnose: compilerInstance.diagnoseFn } + return { cwd: configs.cwd, compile, program: compilerInstance.program } } diff --git a/src/compiler/language-service.spec.ts b/src/compiler/language-service.spec.ts index 34893c0e90..7fba8ab490 100644 --- a/src/compiler/language-service.spec.ts +++ b/src/compiler/language-service.spec.ts @@ -14,13 +14,13 @@ describe('language service', () => { }) it('should use the cache', () => { - const tmp = tempDir('compiler'), - compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp }, - tsJestConfig: { tsConfig: false }, - }), - source = 'console.log("hello")', - fileName = 'test-cache.ts' + const tmp = tempDir('compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, + tsJestConfig: { tsConfig: false }, + }) + const source = 'console.log("hello")' + const fileName = 'test-cache.ts' writeFileSync(fileName, source, 'utf8') @@ -36,6 +36,8 @@ describe('language service', () => { "[level:20] updateMemoryCache(): update memory cache for language service ", "[level:20] visitSourceFileNode(): hoisting + ", + "[level:20] diagnoseFn(): computing diagnostics for test-cache.ts using language service ", "[level:20] readThrough(): writing caches ", @@ -59,11 +61,11 @@ describe('language service', () => { }) it('should compile js file for allowJs true', () => { - const fileName = `test-allow-js.js`, - compiler = makeCompiler({ - tsJestConfig: { tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } }, - }), - source = 'export default 42' + const fileName = `test-allow-js.js` + const compiler = makeCompiler({ + tsJestConfig: { tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } }, + }) + const source = 'export default 42' writeFileSync(fileName, source, 'utf8') const compiled = compiler.compile(source, fileName) @@ -74,15 +76,15 @@ describe('language service', () => { }) it('should compile tsx file for jsx preserve', () => { - const fileName = 'test-jsx-preserve.tsx', - compiler = makeCompiler({ - tsJestConfig: { - tsConfig: { - jsx: 'preserve' as any, - }, + const fileName = 'test-jsx-preserve.tsx' + const compiler = makeCompiler({ + tsJestConfig: { + tsConfig: { + jsx: 'preserve' as any, }, - }), - source = ` + }, + }) + const source = ` const App = () => { return <>Test } @@ -96,15 +98,15 @@ describe('language service', () => { }) it('should compile tsx file for other jsx options', () => { - const fileName = 'test-jsx-options.tsx', - compiler = makeCompiler({ - tsJestConfig: { - tsConfig: { - jsx: 'react' as any, - }, + const fileName = 'test-jsx-options.tsx' + const compiler = makeCompiler({ + tsJestConfig: { + tsConfig: { + jsx: 'react' as any, }, - }), - source = ` + }, + }) + const source = ` const App = () => { return <>Test } @@ -118,9 +120,9 @@ describe('language service', () => { }) it('should have correct source maps', () => { - const compiler = makeCompiler({ tsJestConfig: { tsConfig: false } }), - source = 'const gsm = (v: number) => v\nconst h: number = gsm(5)', - fileName = 'test-source-map.ts' + const compiler = makeCompiler({ tsJestConfig: { tsConfig: false } }) + const source = 'const gsm = (v: number) => v\nconst h: number = gsm(5)' + const fileName = 'test-source-map.ts' writeFileSync(fileName, source, 'utf8') const compiled = compiler.compile(source, fileName) @@ -135,49 +137,47 @@ describe('language service', () => { }) it('should report diagnostics related to typings with pathRegex config matches file name', () => { - const fileName = 'test-match-regex-diagnostics.ts', - source = ` + const fileName = 'test-match-regex-diagnostics.ts' + const source = ` const g = (v: number) => v const x: string = g(5) -`, - compiler = makeCompiler({ - tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: fileName } }, - }) +` + const compiler = makeCompiler({ + tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: fileName } }, + }) writeFileSync(fileName, source, 'utf8') - compiler.compile(source, fileName) - expect(() => compiler.diagnose!(source, fileName)).toThrowErrorMatchingSnapshot() + expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot() removeSync(fileName) }) it('should not report diagnostics related to typings with pathRegex config does not match file name', () => { - const fileName = 'test-non-match-regex-diagnostics.ts', - source = ` + const fileName = 'test-non-match-regex-diagnostics.ts' + const source = ` const f = (v: number) => v const t: string = f(5) -`, - compiler = makeCompiler({ - tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: 'bar.ts' } }, - }) +` + const compiler = makeCompiler({ + tsJestConfig: { tsConfig: false, diagnostics: { pathRegex: 'bar.ts' } }, + }) writeFileSync(fileName, source, 'utf8') - compiler.compile(source, fileName) - expect(() => compiler.diagnose!(source, fileName)).not.toThrowError() + expect(() => compiler.compile(source, fileName)).not.toThrowError() removeSync(fileName) }) it('should throw error when cannot compile', () => { - const fileName = 'test-cannot-compile.d.ts', - source = ` + const fileName = 'test-cannot-compile.d.ts' + const source = ` interface Foo { a: string } - `, - compiler = makeCompiler({ - tsJestConfig: { tsConfig: false }, - }) + ` + const compiler = makeCompiler({ + tsJestConfig: { tsConfig: false }, + }) writeFileSync(fileName, source, 'utf8') expect(() => compiler.compile(source, fileName)).toThrowErrorMatchingSnapshot() diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index 25a8082cbb..ed18aef5b7 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -1,5 +1,6 @@ import { LogContexts, LogLevels, Logger } from 'bs-logger' import memoize = require('lodash.memoize') +import micromatch = require('micromatch') import { basename, normalize, relative } from 'path' import * as _ts from 'typescript' @@ -7,7 +8,16 @@ import { ConfigSet } from '../config/config-set' import { CompilerInstance, MemoryCache, SourceOutput } from '../types' import { Errors, interpolate } from '../util/messages' -const hasOwn = Object.prototype.hasOwnProperty +import { cacheResolvedModules, hasOwn } from './compiler-utils' + +function doTypeChecking(configs: ConfigSet, fileName: string, service: _ts.LanguageService, logger: Logger) { + if (configs.shouldReportDiagnostic(fileName)) { + // Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`. + const diagnostics = service.getSemanticDiagnostics(fileName).concat(service.getSyntacticDiagnostics(fileName)) + // will raise or just warn diagnostics depending on config + configs.raiseDiagnostics(diagnostics, fileName, logger) + } +} /** * @internal @@ -19,21 +29,22 @@ export const compileUsingLanguageService = ( ): CompilerInstance => { logger.debug('compileUsingLanguageService(): create typescript compiler') - const ts = configs.compilerModule, - cwd = configs.cwd, - { options } = configs.typescript, - serviceHostTraceCtx = { - namespace: 'ts:serviceHost', - call: null, - [LogContexts.logLevel]: LogLevels.trace, - } + const ts = configs.compilerModule + const cwd = configs.cwd + const cacheDir = configs.tsCacheDir + const { options } = configs.typescript + const serviceHostTraceCtx = { + namespace: 'ts:serviceHost', + call: null, + [LogContexts.logLevel]: LogLevels.trace, + } let projectVersion = 1 // Set the file contents into cache. const updateMemoryCache = (code: string, fileName: string) => { logger.debug({ fileName }, `updateMemoryCache(): update memory cache for language service`) - const fileVersion = memoryCache.versions[fileName] ?? 0, - isFileInCache = fileVersion !== 0 + const fileVersion = memoryCache.versions[fileName] ?? 0 + const isFileInCache = fileVersion !== 0 if (!isFileInCache) { memoryCache.versions[fileName] = 1 } @@ -48,8 +59,8 @@ export const compileUsingLanguageService = ( getProjectVersion: () => String(projectVersion), getScriptFileNames: () => Object.keys(memoryCache.versions), getScriptVersion: (fileName: string) => { - const normalizedFileName = normalize(fileName), - version = memoryCache.versions[normalizedFileName] + const normalizedFileName = normalize(fileName) + const version = memoryCache.versions[normalizedFileName] // We need to return `undefined` and not a string here because TypeScript will use // `getScriptVersion` and compare against their own version - which can be `undefined`. @@ -59,19 +70,16 @@ export const compileUsingLanguageService = ( return version === undefined ? ((undefined as any) as string) : String(version) }, getScriptSnapshot(fileName: string) { - const normalizedFileName = normalize(fileName), - hit = hasOwn.call(memoryCache.contents, normalizedFileName) + const normalizedFileName = normalize(fileName) + const hit = hasOwn.call(memoryCache.contents, normalizedFileName) logger.trace({ normalizedFileName, cacheHit: hit }, `getScriptSnapshot():`, 'cache', hit ? 'hit' : 'miss') // Read contents from TypeScript memory cache. - if (!hit) { - memoryCache.contents[normalizedFileName] = ts.sys.readFile(normalizedFileName) - } + if (!hit) memoryCache.contents[normalizedFileName] = ts.sys.readFile(normalizedFileName) const contents = memoryCache.contents[normalizedFileName] - if (contents === undefined) { - return - } + + if (contents === undefined) return return ts.ScriptSnapshot.fromString(contents) }, @@ -99,12 +107,44 @@ export const compileUsingLanguageService = ( // Must set memory cache before attempting to read file. updateMemoryCache(code, normalizedFileName) const output: _ts.EmitOutput = service.getEmitOutput(normalizedFileName) - + // Do type checking by getting TypeScript diagnostics + logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using language service`) + + doTypeChecking(configs, normalizedFileName, service, logger) + /** + * We don't need the following logic with no cache run because no cache always gives correct typing + */ + /* istanbul ignore next (covered by e2e) */ + if (cacheDir) { + if (micromatch.isMatch(normalizedFileName, configs.testMatchPatterns)) { + cacheResolvedModules(normalizedFileName, memoryCache, service.getProgram()!, cacheDir, logger) + } else { + /* istanbul ignore next (covered by e2e) */ + Object.entries(memoryCache.resolvedModules) + .filter(entry => { + /** + * When imported modules change, we only need to check whether the test file is compiled previously or not + * base on memory cache. By checking memory cache, we can avoid repeatedly doing type checking against + * test file for 1st time run after clearing cache because + */ + return ( + entry[1].find(modulePath => modulePath === normalizedFileName) && + !hasOwn.call(memoryCache.outputs, entry[0]) + ) + }) + .forEach(entry => { + logger.debug( + `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using language service`, + ) + + doTypeChecking(configs, entry[0], service, logger) + }) + } + } /* istanbul ignore next (this should never happen but is kept for security) */ if (output.emitSkipped) { throw new TypeError(`${relative(cwd, normalizedFileName)}: Emit skipped for language service`) } - // Throw an error when requiring `.d.ts` files. if (!output.outputFiles.length) { throw new TypeError( @@ -116,21 +156,6 @@ export const compileUsingLanguageService = ( return [output.outputFiles[1].text, output.outputFiles[0].text] }, - diagnoseFn: (code: string, filePath: string) => { - const normalizedFileName = normalize(filePath) - updateMemoryCache(code, normalizedFileName) - if (configs.shouldReportDiagnostic(normalizedFileName)) { - logger.debug({ normalizedFileName }, 'compileFn(): computing diagnostics for language service') - - // Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`. - const diagnostics = service - .getCompilerOptionsDiagnostics() - .concat(service.getSyntacticDiagnostics(normalizedFileName)) - .concat(service.getSemanticDiagnostics(normalizedFileName)) - // will raise or just warn diagnostics depending on config - configs.raiseDiagnostics(diagnostics, normalizedFileName, logger) - } - }, program: service.getProgram(), } } diff --git a/src/compiler/program.spec.ts b/src/compiler/program.spec.ts index 183591b132..8761bbbd47 100644 --- a/src/compiler/program.spec.ts +++ b/src/compiler/program.spec.ts @@ -13,93 +13,9 @@ const baseTsJestConfig = { compilerHost: true, } -describe('typings', () => { - const fileName = 'test-typings.ts', - source = ` -const f = (v: number) => v -const t: string = f(5) -` - - beforeAll(() => { - writeFileSync(fileName, source, 'utf8') - }) - - afterAll(() => { - 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 }, - }, - }) - - try { - compiler.compile(source, fileName) - } catch (e) {} - - expect(() => compiler.diagnose!(source, fileName)).toThrowErrorMatchingSnapshot() - }) - - 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(() => compiler.diagnose!(source, fileName)).not.toThrowError() - }) - }) - - describe('incremental program', () => { - it('should report diagnostics with pathRegex config matches file name', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - diagnostics: { pathRegex: fileName }, - }, - }) - - try { - compiler.compile(source, fileName) - } catch (e) {} - - expect(() => compiler.diagnose!(source, fileName)).toThrowErrorMatchingSnapshot() - }) - - 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(() => compiler.diagnose!(source, fileName)).not.toThrowError() - }) - }) -}) - -describe('source-maps', () => { - const fileName = 'source-maps-test.ts', - source = 'console.log("hello")' +describe('cache', () => { + const fileName = 'test-cache.ts' + const source = 'console.log("hello")' beforeAll(() => { writeFileSync(fileName, source, 'utf8') @@ -109,74 +25,29 @@ describe('source-maps', () => { removeSync(fileName) }) - it('should have correct source maps with normal program', () => { + it('should use the cache with normal program', () => { + const tmp = tempDir('program-compiler') const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, 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', () => { - const compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - }, - }) - - const compiled = compiler.compile(source, fileName) - - expect(new ProcessedSource(compiled, fileName).outputSourceMaps).toMatchObject({ - file: fileName, - sources: [fileName], - sourcesContent: [source], - }) - }) -}) - -describe('cache', () => { - const fileName = 'test-cache.ts', - source = 'console.log("hello")' - - beforeAll(() => { - writeFileSync(fileName, source, 'utf8') - }) - - afterAll(() => { - removeSync(fileName) - }) - - it('should use the cache with normal program', () => { - const tmp = tempDir('program-compiler'), - 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] compileFn(): compiling using program ", "[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.ts using program ", "[level:20] readThrough(): writing caches ", @@ -196,31 +67,33 @@ describe('cache', () => { }) it('should use the cache with incremental program', () => { - const tmp = tempDir('incremental-program-compiler'), - compiler = makeCompiler({ - jestConfig: { cache: true, cacheDirectory: tmp }, - tsJestConfig: { - ...baseTsJestConfig, - incremental: true, - }, - }) + const tmp = tempDir('incremental-program-compiler') + const compiler = makeCompiler({ + jestConfig: { cache: true, cacheDirectory: tmp }, + tsJestConfig: { + ...baseTsJestConfig, + incremental: true, + }, + }) logTarget.clear() const compiled1 = compiler.compile(source, fileName) expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(` -Array [ - "[level:20] readThrough(): cache miss -", - "[level:20] compileFn(): compiling using incremental program -", - "[level:20] updateMemoryCache(): update memory cache for incremental program -", - "[level:20] visitSourceFileNode(): hoisting -", - "[level:20] readThrough(): writing caches -", -] -`) + Array [ + "[level:20] readThrough(): cache miss + ", + "[level:20] updateMemoryCache(): update memory cache for incremental program + ", + "[level:20] compileFn(): compiling using incremental program + ", + "[level:20] visitSourceFileNode(): hoisting + ", + "[level:20] diagnoseFn(): computing diagnostics for test-cache.ts using incremental program + ", + "[level:20] readThrough(): writing caches + ", + ] + `) logTarget.clear() const compiled2 = compiler.compile(source, fileName) @@ -236,9 +109,9 @@ Array [ }) describe('allowJs', () => { - const fileName = 'test-allowJs.test.js', - source = 'export default 42', - tsConfig = { allowJs: true, outDir: '$$ts-jest$$' } + const fileName = 'test-allowJs.test.js' + const source = 'export default 42' + const tsConfig = { allowJs: true, outDir: '$$ts-jest$$' } beforeAll(() => { writeFileSync(fileName, source, 'utf8') @@ -270,15 +143,15 @@ describe('allowJs', () => { }) describe('jsx preserve', () => { - const fileName = 'test-jsx-preserve.tsx', - source = ` + const fileName = 'test-jsx-preserve.tsx' + const source = ` const App = () => { return <>Test } - `, - tsConfig = { - jsx: 'preserve' as any, - } + ` + const tsConfig = { + jsx: 'preserve' as any, + } beforeAll(() => { writeFileSync(fileName, source, 'utf8') @@ -310,15 +183,15 @@ describe('jsx preserve', () => { }) describe('other jsx options', () => { - const fileName = 'test-jsx-options.tsx', - source = ` + const fileName = 'test-jsx-options.tsx' + const source = ` const App = () => { return <>Test } - `, - tsConfig = { - jsx: 'react' as any, - } + ` + const tsConfig = { + jsx: 'react' as any, + } beforeAll(() => { writeFileSync(fileName, source, 'utf8') @@ -349,10 +222,133 @@ describe('other jsx options', () => { }) }) +describe('diagnostics', () => { + const fileName = 'test-typings.ts' + const source = ` +const f = (v: number) => v +const t: string = f(5) +` + + beforeAll(() => { + writeFileSync(fileName, source, 'utf8') + }) + + afterAll(() => { + 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 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') + } + }) + }) + + 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, + incremental: true, + diagnostics: { pathRegex: 'foo.ts' }, + }, + }) + + try { + compiler.compile(source, fileName) + } catch (e) { + expect(e).not.toContain('TypeScript diagnostics') + } + }) + }) +}) + +describe('source-maps', () => { + const fileName = 'source-maps-test.ts' + const source = 'console.log("hello")' + + beforeAll(() => { + writeFileSync(fileName, source, 'utf8') + }) + + afterAll(() => { + 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', () => { + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + incremental: true, + }, + }) + + const compiled = compiler.compile(source, fileName) + + expect(new ProcessedSource(compiled, fileName).outputSourceMaps).toMatchObject({ + file: fileName, + sources: [fileName], + sourcesContent: [source], + }) + }) +}) + describe('cannot compile', () => { - const fileName1 = 'test-cannot-compile.d.ts', - fileName2 = 'test-cannot-compile.jsx', - source = ` + const fileName1 = 'test-cannot-compile.d.ts' + const fileName2 = 'test-cannot-compile.jsx' + const source = ` interface Foo { a: string } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0cef7b999b..d4d925d643 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,5 +1,6 @@ import { LogContexts, LogLevels, Logger } from 'bs-logger' import memoize = require('lodash.memoize') +import micromatch = require('micromatch') import { basename, normalize, relative } from 'path' import * as _ts from 'typescript' @@ -7,7 +8,16 @@ import { ConfigSet } from '../config/config-set' import { CompilerInstance, MemoryCache, SourceOutput } from '../types' import { Errors, interpolate } from '../util/messages' -const hasOwn = Object.prototype.hasOwnProperty +import { cacheResolvedModules, hasOwn } from './compiler-utils' + +function doTypeChecking(configs: ConfigSet, fileName: string, program: _ts.Program, logger: Logger) { + if (configs.shouldReportDiagnostic(fileName)) { + const sourceFile = program.getSourceFile(fileName) + const diagnostics = program.getSemanticDiagnostics(sourceFile).concat(program.getSyntacticDiagnostics(sourceFile)) + // will raise or just warn diagnostics depending on config + configs.raiseDiagnostics(diagnostics, fileName, logger) + } +} /** * @internal @@ -15,30 +25,33 @@ const hasOwn = Object.prototype.hasOwnProperty export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCache: MemoryCache): CompilerInstance => { logger.debug('compileUsingProgram(): create typescript compiler') - const ts = configs.compilerModule, - cwd = configs.cwd, - { options, projectReferences, errors } = configs.typescript, - incremental = configs.tsJest.incremental + 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', - call: null, - [LogContexts.logLevel]: LogLevels.trace, - }, - sys = { - ...ts.sys, - readFile: logger.wrap(compilerHostTraceCtx, 'readFile', memoize(ts.sys.readFile)), - readDirectory: memoize(ts.sys.readDirectory), - getDirectories: memoize(ts.sys.getDirectories), - fileExists: memoize(ts.sys.fileExists), - directoryExists: memoize(ts.sys.directoryExists), - resolvePath: memoize(ts.sys.resolvePath), - realpath: memoize(ts.sys.realpath!), - getCurrentDirectory: () => cwd, - getNewLine: () => '\n', - getCanonicalFileName: (fileName: string) => - ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(), - } - let builderProgram: _ts.EmitAndSemanticDiagnosticsBuilderProgram, program: _ts.Program, host: _ts.CompilerHost + namespace: 'ts:compilerHost', + call: null, + [LogContexts.logLevel]: LogLevels.trace, + } + const sys = { + ...ts.sys, + readFile: logger.wrap(compilerHostTraceCtx, 'readFile', memoize(ts.sys.readFile)), + readDirectory: memoize(ts.sys.readDirectory), + getDirectories: memoize(ts.sys.getDirectories), + fileExists: memoize(ts.sys.fileExists), + directoryExists: memoize(ts.sys.directoryExists), + resolvePath: memoize(ts.sys.resolvePath), + realpath: memoize(ts.sys.realpath!), + getCurrentDirectory: () => cwd, + getNewLine: () => '\n', + 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({ @@ -72,51 +85,43 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa }) } // Read and cache custom transformers. - const customTransformers = configs.tsCustomTransformers, - updateMemoryCache = (code: string, fileName: string): void => { - logger.debug( - { fileName }, - `updateMemoryCache(): update memory cache for ${incremental ? 'incremental program' : 'program'}`, - ) - - const sourceFile = incremental ? builderProgram.getSourceFile(fileName) : program.getSourceFile(fileName) - if (!hasOwn.call(memoryCache.versions, fileName)) { - memoryCache.versions[fileName] = 1 - } - if (memoryCache.contents[fileName] !== code) { - memoryCache.contents[fileName] = code - memoryCache.versions[fileName] = (memoryCache.versions[fileName] || 0) + 1 + const customTransformers = configs.tsCustomTransformers + const updateMemoryCache = (code: string, fileName: string): void => { + logger.debug({ fileName }, `updateMemoryCache(): update memory cache for ${programDebugText}`) + + const sourceFile = incremental ? builderProgram.getSourceFile(fileName) : program.getSourceFile(fileName) + if (!hasOwn.call(memoryCache.versions, fileName)) { + memoryCache.versions[fileName] = 1 + } + if (memoryCache.contents[fileName] !== code) { + memoryCache.contents[fileName] = code + memoryCache.versions[fileName] = (memoryCache.versions[fileName] || 0) + 1 + } + // Update program when file changes. + if (sourceFile === undefined || sourceFile.text !== code || program.isSourceFileFromExternalLibrary(sourceFile)) { + const programOptions = { + rootNames: Object.keys(memoryCache.versions), + options, + host, + configFileParsingDiagnostics: errors, + projectReferences, } - // Update program when file changes. - if (sourceFile === undefined || sourceFile.text !== code || program.isSourceFileFromExternalLibrary(sourceFile)) { - const programOptions = { - rootNames: Object.keys(memoryCache.versions), - options, - host, - configFileParsingDiagnostics: errors, - projectReferences, - } - if (incremental) { - builderProgram = ts.createIncrementalProgram(programOptions) - program = builderProgram.getProgram() - } else { - program = ts.createProgram({ - ...programOptions, - oldProgram: program, - }) - } + if (incremental) { + builderProgram = ts.createIncrementalProgram(programOptions) + program = builderProgram.getProgram() + } else { + program = ts.createProgram({ + ...programOptions, + oldProgram: program, + }) } } + } return { compileFn: (code: string, fileName: string): SourceOutput => { - const normalizedFileName = normalize(fileName), - output: [string, string] = ['', ''] - - logger.debug( - { normalizedFileName }, - `compileFn(): compiling using ${incremental ? 'incremental program' : 'program'}`, - ) + const normalizedFileName = normalize(fileName) + const output: [string, string] = ['', ''] // Must set memory cache before attempting to read file. updateMemoryCache(code, normalizedFileName) const sourceFile = incremental @@ -125,6 +130,8 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa 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, @@ -144,7 +151,40 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa undefined, customTransformers, ) + // Do type checking by getting TypeScript diagnostics + logger.debug(`diagnoseFn(): computing diagnostics for ${normalizedFileName} using ${programDebugText}`) + doTypeChecking(configs, normalizedFileName, program, logger) + /** + * We don't need the following logic with no cache run because no cache always gives correct typing + */ + /* istanbul ignore next (covered by e2e) */ + if (cacheDir) { + if (micromatch.isMatch(normalizedFileName, configs.testMatchPatterns)) { + cacheResolvedModules(normalizedFileName, memoryCache, program, cacheDir, logger) + } else { + /* istanbul ignore next (covered by e2e) */ + Object.entries(memoryCache.resolvedModules) + .filter(entry => { + /** + * When imported modules change, we only need to check whether the test file is compiled previously or not + * base on memory cache. By checking memory cache, we can avoid repeatedly doing type checking against + * test file for 1st time run after clearing cache because + */ + return ( + entry[1].find(modulePath => modulePath === normalizedFileName) && + !hasOwn.call(memoryCache.outputs, entry[0]) + ) + }) + .forEach(entry => { + logger.debug( + `diagnoseFn(): computing diagnostics for test file that imports ${normalizedFileName} using ${programDebugText}`, + ) + + doTypeChecking(configs, entry[0], program, logger) + }) + } + } if (result.emitSkipped) { throw new TypeError(`${relative(cwd, fileName)}: Emit skipped`) } @@ -160,21 +200,6 @@ export const compileUsingProgram = (configs: ConfigSet, logger: Logger, memoryCa return output }, - diagnoseFn: (code: string, filePath: string) => { - const normalizedFileName = normalize(filePath) - updateMemoryCache(code, normalizedFileName) - if (configs.shouldReportDiagnostic(normalizedFileName)) { - logger.debug( - { normalizedFileName }, - `compileFn(): computing diagnostics for ${incremental ? 'incremental program' : 'program'}`, - ) - - const sourceFile = program.getSourceFile(normalizedFileName), - diagnostics = program.getSemanticDiagnostics(sourceFile).concat(program.getSyntacticDiagnostics(sourceFile)) - // will raise or just warn diagnostics depending on config - configs.raiseDiagnostics(diagnostics, normalizedFileName, logger) - } - }, program, } } diff --git a/src/compiler/transpile-module.spec.ts b/src/compiler/transpile-module.spec.ts index 855998628b..67e5d0cb71 100644 --- a/src/compiler/transpile-module.spec.ts +++ b/src/compiler/transpile-module.spec.ts @@ -17,8 +17,8 @@ describe('transpile module with isolatedModule: true', () => { }) it('should compile using transpileModule and not use cache', () => { - const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }), - spy = jest.spyOn(require('typescript'), 'transpileModule') + const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }) + const spy = jest.spyOn(require('typescript'), 'transpileModule') logTarget.clear() const compiled = compiler.compile('export default 42', __filename) @@ -40,11 +40,11 @@ describe('transpile module with isolatedModule: true', () => { }) it('should compile js file for allowJs true', () => { - const fileName = `${__filename}.test.js`, - compiler = makeCompiler({ - tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } }, - }), - source = 'export default 42' + const fileName = `${__filename}.test.js` + const compiler = makeCompiler({ + tsJestConfig: { ...baseTsJestConfig, tsConfig: { allowJs: true, outDir: '$$ts-jest$$' } }, + }) + const source = 'export default 42' writeFileSync(fileName, source, 'utf8') const compiled = compiler.compile(source, fileName) @@ -55,16 +55,16 @@ describe('transpile module with isolatedModule: true', () => { }) it('should compile tsx file for jsx preserve', () => { - const fileName = `foo.tsx`, - compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - tsConfig: { - jsx: 'preserve' as any, - }, + const fileName = `foo.tsx` + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + tsConfig: { + jsx: 'preserve' as any, }, - }), - source = ` + }, + }) + const source = ` const App = () => { return <>Test } @@ -79,16 +79,16 @@ describe('transpile module with isolatedModule: true', () => { }) it('should compile tsx file for other jsx options', () => { - const fileName = `foo.tsx`, - compiler = makeCompiler({ - tsJestConfig: { - ...baseTsJestConfig, - tsConfig: { - jsx: 'react' as any, - }, + const fileName = `foo.tsx` + const compiler = makeCompiler({ + tsJestConfig: { + ...baseTsJestConfig, + tsConfig: { + jsx: 'react' as any, }, - }), - source = ` + }, + }) + const source = ` const App = () => { return <>Test } @@ -103,8 +103,8 @@ describe('transpile module with isolatedModule: true', () => { }) it('should have correct source maps', () => { - const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }), - source = 'const f = (v: number) => v\nconst t: number = f(5)' + const compiler = makeCompiler({ tsJestConfig: { ...baseTsJestConfig, tsConfig: false } }) + const source = 'const f = (v: number) => v\nconst t: number = f(5)' const compiled = compiler.compile(source, __filename) diff --git a/src/compiler/transpile-module.ts b/src/compiler/transpile-module.ts index 8d04ad94e9..cc7cb6c2cb 100644 --- a/src/compiler/transpile-module.ts +++ b/src/compiler/transpile-module.ts @@ -14,13 +14,13 @@ export const compileUsingTranspileModule = (configs: ConfigSet, logger: Logger): compileFn: (code: string, fileName: string): SourceOutput => { logger.debug({ fileName }, 'getOutput(): compiling as isolated module') - const normalizedFileName = normalize(fileName), - result = configs.compilerModule.transpileModule(code, { - fileName: normalizedFileName, - transformers: configs.tsCustomTransformers, - compilerOptions: configs.typescript.options, - reportDiagnostics: configs.shouldReportDiagnostic(normalizedFileName), - }) + const normalizedFileName = normalize(fileName) + const result = configs.compilerModule.transpileModule(code, { + fileName: normalizedFileName, + transformers: configs.tsCustomTransformers, + compilerOptions: configs.typescript.options, + reportDiagnostics: configs.shouldReportDiagnostic(normalizedFileName), + }) if (result.diagnostics && configs.shouldReportDiagnostic(normalizedFileName)) { configs.raiseDiagnostics(result.diagnostics, normalizedFileName, logger) diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts index abfe04013c..5f99046a1c 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -462,10 +462,6 @@ describe('typescript', () => { }) }) - it('should include default outDir $$ts-jest$$ when allowJs is enabled and no outDir from config', () => { - expect(get(void 0, { tsConfig: { allowJs: true } }).options.outDir).toBe('$$ts-jest$$') - }) - it('should be able to read extends', () => { const cs = createConfigSet({ tsJestConfig: { tsConfig: 'tsconfig.build.json' }, diff --git a/src/config/config-set.ts b/src/config/config-set.ts index f0a378fa4d..276bdeb9df 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -187,6 +187,14 @@ export class ConfigSet { return config } + /** + * @internal + */ + @Memoize() + get testMatchPatterns(): string[] { + return this.jest.testMatch.concat(this.jest.testRegex) + } + /** * @internal */ @@ -770,10 +778,6 @@ export class ConfigSet { finalOptions.allowSyntheticDefaultImports = true } } - // Make sure when allowJs is enabled, outDir is set otherwise we run into error: Cannot write file ... because it would overwrite input - if (finalOptions.allowJs && !finalOptions.outDir) { - finalOptions.outDir = '$$ts-jest$$' - } // ensure undefined are removed and other values are overridden for (const key of Object.keys(forcedOptions)) { diff --git a/src/ts-jest-transformer.spec.ts b/src/ts-jest-transformer.spec.ts index 6165edb061..7c7e52a5a8 100644 --- a/src/ts-jest-transformer.spec.ts +++ b/src/ts-jest-transformer.spec.ts @@ -238,20 +238,11 @@ Array [ }) describe('getCacheKey', () => { - let tr: TsJestTransformer - - beforeEach(() => { - tr = new TsJestTransformer() - }) - it('should be different for each argument value', () => { - jest.spyOn(tr, 'configsFor').mockImplementation( - jestConfigStr => - (({ - cacheKey: jestConfigStr, - tsCompiler: {}, - } as unknown) as ConfigSet), - ) + const tr = new TsJestTransformer() + jest + .spyOn(tr, 'configsFor') + .mockImplementation(jestConfigStr => (({ cacheKey: jestConfigStr } as unknown) as ConfigSet)) const input = { fileContent: 'export default "foo"', fileName: 'foo.ts', @@ -272,52 +263,4 @@ describe('getCacheKey', () => { // unique array should have same length expect(keys.filter((k, i, all) => all.indexOf(k) === i)).toHaveLength(keys.length) }) - - it('should call diagnose() to do type checking for js/jsx/ts/tsx file but not d.ts file', () => { - const tsCompilerStub = { diagnose: jest.fn() }, - baseInput = { - fileContent: 'export default "foo"', - jestConfigStr: '{"foo": "bar"}', - options: { instrument: false, rootDir: '/foo' }, - } - jest.spyOn(tr, 'configsFor').mockImplementation( - jestConfigStr => - (({ - cacheKey: jestConfigStr, - tsCompiler: tsCompilerStub, - } as unknown) as ConfigSet), - ) - const jsInput = { - ...baseInput, - fileName: 'foo.js', - }, - jsxInput = { - ...baseInput, - fileName: 'foo.jsx', - }, - tsInput = { - ...baseInput, - fileName: 'foo.ts', - }, - tsxInput = { - ...baseInput, - fileName: 'foo.tsx', - }, - dtsInput = { - ...baseInput, - fileContent: 'type Foo = (code: string) => void', - fileName: 'foo.d.ts', - } - tr.getCacheKey(jsInput.fileContent, jsInput.fileName, jsInput.jestConfigStr, jsInput.options) - tr.getCacheKey(jsxInput.fileContent, jsxInput.fileName, jsxInput.jestConfigStr, jsxInput.options) - tr.getCacheKey(tsInput.fileContent, tsInput.fileName, tsInput.jestConfigStr, tsInput.options) - tr.getCacheKey(tsxInput.fileContent, tsxInput.fileName, tsxInput.jestConfigStr, tsxInput.options) - tr.getCacheKey(dtsInput.fileContent, dtsInput.fileName, dtsInput.jestConfigStr, dtsInput.options) - - expect(tsCompilerStub.diagnose).toHaveBeenCalledTimes(4) - expect(tsCompilerStub.diagnose).toHaveBeenNthCalledWith(1, jsInput.fileContent, jsInput.fileName) - expect(tsCompilerStub.diagnose).toHaveBeenNthCalledWith(2, jsxInput.fileContent, jsxInput.fileName) - expect(tsCompilerStub.diagnose).toHaveBeenNthCalledWith(3, tsInput.fileContent, tsInput.fileName) - expect(tsCompilerStub.diagnose).toHaveBeenNthCalledWith(4, tsxInput.fileContent, tsxInput.fileName) - }) }) diff --git a/src/ts-jest-transformer.ts b/src/ts-jest-transformer.ts index 641121a21f..d4e7514706 100644 --- a/src/ts-jest-transformer.ts +++ b/src/ts-jest-transformer.ts @@ -18,18 +18,6 @@ interface ConfigSetIndexItem { jestConfig: JsonableValue } -function checkDefinitionFile(filePath: string): boolean { - return filePath.endsWith('.d.ts') -} - -function checkJsFile(filePath: string): boolean { - return /\.jsx?$/.test(filePath) -} - -function checkTsFile(filePath: string): boolean { - return !checkDefinitionFile(filePath) && /\.tsx?$/.test(filePath) -} - export class TsJestTransformer implements Transformer { /** * @internal @@ -114,14 +102,14 @@ export class TsJestTransformer implements Transformer { this.logger.debug({ fileName: filePath, transformOptions }, 'processing', filePath) let result: string | TransformedSource - const source: string = input, - configs = this.configsFor(jestConfig), - { hooks } = configs, - stringify = configs.shouldStringifyContent(filePath), - babelJest = stringify ? undefined : configs.babelJestTransformer, - isDefinitionFile = checkDefinitionFile(filePath), - isJsFile = checkJsFile(filePath), - isTsFile = checkTsFile(filePath) + const source: string = input + const configs = this.configsFor(jestConfig) + const { hooks } = configs + const stringify = configs.shouldStringifyContent(filePath) + const babelJest = stringify ? undefined : configs.babelJestTransformer + const isDefinitionFile = filePath.endsWith('.d.ts') + const isJsFile = /\.jsx?$/.test(filePath) + const isTsFile = !isDefinitionFile && /\.tsx?$/.test(filePath) if (stringify) { // handles here what we should simply stringify result = `module.exports=${JSON.stringify(source)}` @@ -189,9 +177,6 @@ export class TsJestTransformer implements Transformer { const configs = this.configsFor(jestConfigStr) // we do not instrument, ensure it is false all the time const { instrument = false, rootDir = configs.rootDir } = transformOptions - if (configs.tsCompiler.diagnose && (checkJsFile(filePath) || checkTsFile(filePath))) { - configs.tsCompiler.diagnose(fileContent, filePath) - } return sha1( configs.cacheKey, diff --git a/src/types.ts b/src/types.ts index 0f7d144bed..c50b63f2ea 100644 --- a/src/types.ts +++ b/src/types.ts @@ -185,10 +185,6 @@ export interface TsCompiler { * @internal */ compile(code: string, fileName: string, lineOffset?: number): string - /** - * @internal - */ - diagnose: DiagnoseFn | undefined program: _ts.Program | undefined } @@ -206,21 +202,17 @@ export interface MemoryCache { contents: { [filePath: string]: string | undefined } versions: { [filePath: string]: number } outputs: { [filePath: string]: string } + resolvedModules: { [testFilePath: string]: string[] } } /** * @internal */ export type CompileFn = (code: string, fileName: string, lineOffset?: number) => SourceOutput -/** - * @internal - */ -export type DiagnoseFn = (code: string, filePath: string) => void /** * @internal */ export interface CompilerInstance { compileFn: CompileFn - diagnoseFn?: DiagnoseFn program?: _ts.Program } /** diff --git a/tslint.json b/tslint.json index e21fb54d77..7669513b00 100644 --- a/tslint.json +++ b/tslint.json @@ -47,7 +47,6 @@ "no-string-throw": true, "no-var-keyword": true, "object-literal-sort-keys": false, - "one-variable-per-declaration": false, "ordered-imports": [ true, {