diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index 901f05bdca..920e18ecfc 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -71,7 +71,7 @@ const compileAndCacheResult = ( export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { const logger = configs.logger.child({ namespace: 'ts-compiler' }) const { - typescript: { options: compilerOptions }, + parsedTsConfig: { options: compilerOptions }, tsJest, } = configs const cacheDir = configs.tsCacheDir @@ -96,7 +96,7 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { } catch (e) {} } // Initialize memory cache for typescript compiler - configs.typescript.fileNames.forEach(fileName => { + configs.parsedTsConfig.fileNames.forEach(fileName => { memoryCache.files.set(fileName, { version: 0, }) diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index e610d60a3e..69eea6fd3c 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -37,7 +37,7 @@ export const initializeLanguageServiceInstance = ( const ts = configs.compilerModule const cwd = configs.cwd const cacheDir = configs.tsCacheDir - const { options, projectReferences, fileNames } = configs.typescript + const { options, projectReferences, fileNames } = configs.parsedTsConfig const serviceHostTraceCtx = { namespace: 'ts:serviceHost', call: null, diff --git a/src/compiler/transpiler.ts b/src/compiler/transpiler.ts index c25b844234..acb88b1765 100644 --- a/src/compiler/transpiler.ts +++ b/src/compiler/transpiler.ts @@ -16,7 +16,7 @@ export const initializeTranspilerInstance = ( ): CompilerInstance => { logger.debug('initializeTranspilerInstance(): create typescript compiler') - const { options, projectReferences, fileNames } = configs.typescript + const { options, projectReferences, fileNames } = configs.parsedTsConfig const ts = configs.compilerModule const program = projectReferences ? ts.createProgram({ diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts index 4d804f3680..527416ac23 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -471,7 +471,7 @@ describe('makeDiagnostic', () => { describe('typescript', () => { const get = (tsJest?: TsJestGlobalOptions, parentConfig?: TsJestGlobalOptions) => - createConfigSet({ tsJestConfig: tsJest, parentConfig }).typescript + createConfigSet({ tsJestConfig: tsJest, parentConfig }).parsedTsConfig it('should read file list from default tsconfig', () => { // since the default is to lookup for tsconfig, but we set include to [] so we should not have this file in the list @@ -502,7 +502,7 @@ describe('typescript', () => { tsJestConfig: { tsConfig: 'tsconfig.build.json' }, resolve: null, }) - expect(cs.typescript.options).toMatchObject({ + expect(cs.parsedTsConfig.options).toMatchObject({ module: ts.ModuleKind.CommonJS, rootDir: normalizeSlashes(resolve(__dirname, '..')), skipLibCheck: true, @@ -519,7 +519,7 @@ describe('typescript', () => { }, resolve: null, }) - expect(cs.typescript.options).toMatchObject({ + expect(cs.parsedTsConfig.options).toMatchObject({ module: ts.ModuleKind.CommonJS, allowSyntheticDefaultImports: true, esModuleInterop: false, @@ -541,11 +541,11 @@ describe('typescript', () => { }, resolve: null, }) - expect(cs.typescript.options).toMatchObject({ + expect(cs.parsedTsConfig.options).toMatchObject({ module: ts.ModuleKind.AMD, esModuleInterop: false, }) - expect(cs.typescript.options.allowSyntheticDefaultImports).toBeFalsy() + expect(cs.parsedTsConfig.options.allowSyntheticDefaultImports).toBeFalsy() expect(target.lines.warn).toHaveLength(0) }) }) // typescript @@ -582,11 +582,13 @@ describe('readTsConfig', () => { let readConfig!: jest.SpyInstance<{ config?: any; error?: ts.Diagnostic }> let parseConfig!: jest.SpyInstance let cs!: ConfigSet + beforeAll(() => { findConfig = jest.spyOn(ts, 'findConfigFile') readConfig = jest.spyOn(ts, 'readConfigFile') parseConfig = jest.spyOn(ts, 'parseJsonConfigFileContent') }) + afterAll(() => { findConfig.mockRestore() readConfig.mockRestore() @@ -603,6 +605,7 @@ describe('readTsConfig', () => { } as any, }) }) + afterEach(() => { findConfig.mockClear() readConfig.mockClear() @@ -611,7 +614,7 @@ describe('readTsConfig', () => { it('should use correct paths when searching', () => { const conf = cs.readTsConfig() - expect(conf.input).toBeUndefined() + expect(conf.options.configFilePath).toBeUndefined() expect(readConfig).not.toHaveBeenCalled() expect(parseConfig.mock.calls[0][0]).toEqual( expect.objectContaining({ @@ -621,9 +624,10 @@ describe('readTsConfig', () => { expect(parseConfig.mock.calls[0][2]).toBe('/root') expect(parseConfig.mock.calls[0][4]).toBeUndefined() }) + it('should use given tsconfig path', () => { const conf = cs.readTsConfig(undefined, '/foo/tsconfig.bar.json') - expect(conf.input).toBeUndefined() + expect(conf.options.configFilePath).toBeUndefined() expect(findConfig).not.toBeCalled() expect(readConfig.mock.calls[0][0]).toBe('/foo/tsconfig.bar.json') expect(parseConfig).not.toHaveBeenCalled() @@ -636,10 +640,12 @@ describe('readTsConfig', () => { findConfig.mockImplementation(p => `${p}/tsconfig.json`) readConfig.mockImplementation(p => ({ config: { path: p, compilerOptions: {} } })) }) + afterEach(() => { findConfig.mockClear() readConfig.mockClear() }) + describe('module in tsConfig is not the same as forced module and esModuleInterop is not in tsConfig', () => { beforeEach(() => { parseConfig.mockImplementation((conf: any) => ({ @@ -651,13 +657,14 @@ describe('readTsConfig', () => { errors: [], })) }) + afterEach(() => { parseConfig.mockClear() }) it('should use correct paths when searching', () => { const conf = cs.readTsConfig() - expect(conf.input.path).toBe('/root/tsconfig.json') + expect(conf.options.path).toBe('/root/tsconfig.json') expect(findConfig.mock.calls[0][0]).toBe('/root') expect(readConfig.mock.calls[0][0]).toBe('/root/tsconfig.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -667,13 +674,13 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/root') expect(parseConfig.mock.calls[0][4]).toBe('/root/tsconfig.json') - expect(conf.resolved.options.allowSyntheticDefaultImports).toEqual(true) - expect(conf.resolved.errors).toMatchSnapshot() + expect(conf.options.allowSyntheticDefaultImports).toEqual(true) + expect(conf.errors).toMatchSnapshot() }) it('should use given tsconfig path', () => { const conf = cs.readTsConfig(undefined, '/foo/tsconfig.bar.json') - expect(conf.input.path).toBe('/foo/tsconfig.bar.json') + expect(conf.options.path).toBe('/foo/tsconfig.bar.json') expect(findConfig).not.toBeCalled() expect(readConfig.mock.calls[0][0]).toBe('/foo/tsconfig.bar.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -683,7 +690,7 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/foo') expect(parseConfig.mock.calls[0][4]).toBe('/foo/tsconfig.bar.json') - expect(conf.resolved.errors).toMatchSnapshot() + expect(conf.errors).toMatchSnapshot() }) }) @@ -699,13 +706,14 @@ describe('readTsConfig', () => { errors: [], })) }) + afterEach(() => { parseConfig.mockClear() }) it('should use correct paths when searching', () => { const conf = cs.readTsConfig() - expect(conf.input.path).toBe('/root/tsconfig.json') + expect(conf.options.path).toBe('/root/tsconfig.json') expect(findConfig.mock.calls[0][0]).toBe('/root') expect(readConfig.mock.calls[0][0]).toBe('/root/tsconfig.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -715,18 +723,18 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/root') expect(parseConfig.mock.calls[0][4]).toBe('/root/tsconfig.json') - expect(conf.resolved.options.allowSyntheticDefaultImports).toEqual(true) - expect(conf.resolved.errors).toMatchSnapshot() + expect(conf.options.allowSyntheticDefaultImports).toEqual(true) + expect(conf.errors).toMatchSnapshot() }) it('should use given tsconfig path', () => { const conf = cs.readTsConfig(undefined, '/foo/tsconfig.bar.json') - expect(conf.input.path).toBe('/foo/tsconfig.bar.json') + expect(conf.options.path).toBe('/foo/tsconfig.bar.json') expect(findConfig).not.toBeCalled() expect(readConfig.mock.calls[0][0]).toBe('/foo/tsconfig.bar.json') expect(parseConfig.mock.calls[0][2]).toBe('/foo') expect(parseConfig.mock.calls[0][4]).toBe('/foo/tsconfig.bar.json') - expect(conf.resolved.errors).toMatchSnapshot() + expect(conf.errors).toMatchSnapshot() }) }) @@ -742,13 +750,14 @@ describe('readTsConfig', () => { errors: [], })) }) + afterEach(() => { parseConfig.mockClear() }) it('should use correct paths when searching', () => { const conf = cs.readTsConfig() - expect(conf.input.path).toBe('/root/tsconfig.json') + expect(conf.options.path).toBe('/root/tsconfig.json') expect(findConfig.mock.calls[0][0]).toBe('/root') expect(readConfig.mock.calls[0][0]).toBe('/root/tsconfig.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -758,13 +767,13 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/root') expect(parseConfig.mock.calls[0][4]).toBe('/root/tsconfig.json') - expect(conf.resolved.options.allowSyntheticDefaultImports).toBeUndefined() - expect(conf.resolved.errors).toEqual([]) + expect(conf.options.allowSyntheticDefaultImports).toBeUndefined() + expect(conf.errors).toEqual([]) }) it('should use given tsconfig path', () => { const conf = cs.readTsConfig(undefined, '/foo/tsconfig.bar.json') - expect(conf.input.path).toBe('/foo/tsconfig.bar.json') + expect(conf.options.path).toBe('/foo/tsconfig.bar.json') expect(findConfig).not.toBeCalled() expect(readConfig.mock.calls[0][0]).toBe('/foo/tsconfig.bar.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -774,7 +783,7 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/foo') expect(parseConfig.mock.calls[0][4]).toBe('/foo/tsconfig.bar.json') - expect(conf.resolved.errors).toEqual([]) + expect(conf.errors).toEqual([]) }) }) @@ -790,13 +799,14 @@ describe('readTsConfig', () => { errors: [], })) }) + afterEach(() => { parseConfig.mockClear() }) it('should use correct paths when searching', () => { const conf = cs.readTsConfig() - expect(conf.input.path).toBe('/root/tsconfig.json') + expect(conf.options.path).toBe('/root/tsconfig.json') expect(findConfig.mock.calls[0][0]).toBe('/root') expect(readConfig.mock.calls[0][0]).toBe('/root/tsconfig.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -806,13 +816,13 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/root') expect(parseConfig.mock.calls[0][4]).toBe('/root/tsconfig.json') - expect(conf.resolved.errors).toEqual([]) - expect(conf.resolved.options.allowSyntheticDefaultImports).toEqual(true) + expect(conf.errors).toEqual([]) + expect(conf.options.allowSyntheticDefaultImports).toEqual(true) }) it('should use given tsconfig path', () => { const conf = cs.readTsConfig(undefined, '/foo/tsconfig.bar.json') - expect(conf.input.path).toBe('/foo/tsconfig.bar.json') + expect(conf.options.path).toBe('/foo/tsconfig.bar.json') expect(findConfig).not.toBeCalled() expect(readConfig.mock.calls[0][0]).toBe('/foo/tsconfig.bar.json') expect(parseConfig.mock.calls[0][0]).toEqual( @@ -822,8 +832,8 @@ describe('readTsConfig', () => { ) expect(parseConfig.mock.calls[0][2]).toBe('/foo') expect(parseConfig.mock.calls[0][4]).toBe('/foo/tsconfig.bar.json') - expect(conf.resolved.errors).toEqual([]) - expect(conf.resolved.options.allowSyntheticDefaultImports).toEqual(true) + expect(conf.errors).toEqual([]) + expect(conf.options.allowSyntheticDefaultImports).toEqual(true) }) }) }) diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 35412af6bb..7fafe414c3 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -51,13 +51,6 @@ import { TSError } from '../util/ts-error' const logger = rootLogger.child({ namespace: 'config' }) -interface ReadTsConfigResult { - // what we get from reading the config file if any, or inline options - input?: any - // parsed config with all resolved options - resolved: ParsedCommandLine -} - /** * @internal */ @@ -318,8 +311,8 @@ export class ConfigSet { /** * @internal */ - get typescript(): ParsedCommandLine { - return this._typescript.resolved + get parsedTsConfig(): ParsedCommandLine { + return this._parsedTsConfig } /** @@ -346,7 +339,7 @@ export class ConfigSet { * @internal */ @Memoize() - private get _typescript(): ReadTsConfigResult { + private get _parsedTsConfig(): ParsedCommandLine { const { tsJest: { tsConfig }, } = this @@ -357,9 +350,10 @@ export class ConfigSet { tsConfig == null, ) // throw errors if any matching wanted diagnostics - this.raiseDiagnostics(result.resolved.errors, configFilePath) + this.raiseDiagnostics(result.errors, configFilePath) this.logger.debug({ tsconfig: result }, 'normalized typescript config') + return result } @@ -577,7 +571,7 @@ export class ConfigSet { digest: this.tsJestDigest, dependencies: this.projectDependencies, compiler: this.tsJest.compiler, - compilerOptions: this.typescript.options, + compilerOptions: this.parsedTsConfig.options, isolatedModules: this.tsJest.isolatedModules, diagnostics: this.tsJest.diagnostics, }), @@ -667,7 +661,7 @@ export class ConfigSet { jest, tsJest: this.tsJest, babel: this.babel, - tsconfig: this.typescript.options, + tsconfig: this.parsedTsConfig.options, }) } @@ -716,16 +710,13 @@ export class ConfigSet { compilerOptions?: object, resolvedConfigFile?: string | null, noProject?: boolean | null, - ): ReadTsConfigResult { + ): ParsedCommandLine { let config = { compilerOptions: {}, include: [] } let basePath = normalizeSlashes(this.rootDir) let configFileName: string | undefined const ts = this.compilerModule - let input: any - if (noProject) { - input = { compilerOptions: { ...compilerOptions } } - } else { + if (!noProject) { // Read project configuration when available. configFileName = resolvedConfigFile ? normalizeSlashes(resolvedConfigFile) @@ -737,23 +728,13 @@ export class ConfigSet { // Return diagnostics. if (result.error) { - return { - resolved: { errors: [result.error], fileNames: [], options: {} }, - } + return { errors: [result.error], fileNames: [], options: {} } } config = result.config - input = { - ...result.config, - compilerOptions: { - ...(result.config && result.config.compilerOptions), - ...compilerOptions, - }, - } basePath = normalizeSlashes(dirname(configFileName)) } } - // Override default configuration options `ts-jest` requires. config.compilerOptions = { ...config.compilerOptions, @@ -813,7 +794,7 @@ export class ConfigSet { } } - return { input, resolved: result } + return result } /** diff --git a/src/ts-jest-transformer.spec.ts b/src/ts-jest-transformer.spec.ts index a02f43ce86..114afc158c 100644 --- a/src/ts-jest-transformer.spec.ts +++ b/src/ts-jest-transformer.spec.ts @@ -28,11 +28,11 @@ describe('configFor', () => { describe('process', () => { let tr: TsJestTransformer let babel: any - let typescript: ParsedCommandLine + let parsedTsConfig: ParsedCommandLine let args: [string, string, any, any] const config = { - get typescript() { - return typescript + get parsedTsConfig() { + return parsedTsConfig }, shouldStringifyContent: jest.fn(), get babelJestTransformer() { @@ -56,7 +56,7 @@ describe('process', () => { config.shouldStringifyContent.mockImplementation(() => false).mockClear() babel = null config.tsCompiler.compile.mockImplementation(s => `ts:${s}`).mockClear() - typescript = { options: {} } as any + parsedTsConfig = { options: {} } as any }) it('should process ts input without babel', () => { @@ -79,7 +79,7 @@ Array [ }) it('should process js input without babel', () => { - typescript.options.allowJs = true + parsedTsConfig.options.allowJs = true args[1] = '/foo/bar.js' expect(process()).toBe(`ts:${INPUT}`) expect(config.shouldStringifyContent.mock.calls).toMatchInlineSnapshot(` @@ -132,7 +132,7 @@ Array [ }) it('should process js input with babel', () => { - typescript.options.allowJs = true + parsedTsConfig.options.allowJs = true babel = { process: jest.fn(s => `babel:${s}`) } args[1] = '/foo/bar.js' expect(process()).toBe(`babel:ts:${INPUT}`) @@ -172,7 +172,7 @@ Array [ it('should warn when trying to process js but allowJs is false', () => { args[1] = '/foo/bar.js' - typescript.options.allowJs = false + parsedTsConfig.options.allowJs = false const logs = logTargetMock() logs.clear() expect(process()).toBe(INPUT) diff --git a/src/ts-jest-transformer.ts b/src/ts-jest-transformer.ts index a3b5040f30..9c1f49623e 100644 --- a/src/ts-jest-transformer.ts +++ b/src/ts-jest-transformer.ts @@ -112,7 +112,7 @@ export class TsJestTransformer implements Transformer { } else if (isDefinitionFile) { // do not try to compile declaration files result = '' - } else if (!configs.typescript.options.allowJs && isJsFile) { + } else if (!configs.parsedTsConfig.options.allowJs && isJsFile) { // we've got a '.js' but the compiler option `allowJs` is not set or set to false this.logger.warn({ fileName: filePath }, interpolate(Errors.GotJsFileButAllowJsFalse, { path: filePath }))