From 0fb6b45e7dc3dd7588d27f09ac9a8849dff470cb Mon Sep 17 00:00:00 2001 From: Ahn Date: Wed, 3 Mar 2021 21:22:24 +0100 Subject: [PATCH] fix(config): create fallback jest config when jest config is undefined (#2421) Closes #2085 --- .../__snapshots__/logger.test.ts.snap | 12 +- src/cli/cli.spec.ts | 399 +++++++++--------- src/config/config-set.ts | 14 +- src/types.ts | 4 +- .../__snapshots__/backports.spec.ts.snap | 65 +++ src/utils/backports.ts | 3 + 6 files changed, 291 insertions(+), 206 deletions(-) diff --git a/e2e/__tests__/__snapshots__/logger.test.ts.snap b/e2e/__tests__/__snapshots__/logger.test.ts.snap index b3c4251ede..8912bdf3ba 100644 --- a/e2e/__tests__/__snapshots__/logger.test.ts.snap +++ b/e2e/__tests__/__snapshots__/logger.test.ts.snap @@ -8,12 +8,12 @@ Array [ "[level:20] checking version of jest: OK", "[level:20] created new transformer", "[level:30] no matching config-set found, creating a new one", + "[level:20] backporting config", + "[level:20] normalized jest config", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] normalized compiler module config via ts-jest option", - "[level:20] backporting config", - "[level:20] normalized jest config", "[level:20] babel is disabled", "[level:20] normalized diagnostics config via ts-jest option", "[level:20] readTsConfig(): reading /tsconfig.json", @@ -47,12 +47,12 @@ Array [ "[level:20] checking version of jest: OK", "[level:20] created new transformer", "[level:30] no matching config-set found, creating a new one", + "[level:20] backporting config", + "[level:20] normalized jest config", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] normalized compiler module config via ts-jest option", - "[level:20] backporting config", - "[level:20] normalized jest config", "[level:20] normalized babel config via ts-jest option", "[level:20] loaded module babel-jest", "[level:20] patching babel-jest", @@ -92,12 +92,12 @@ Array [ "[level:20] checking version of jest: OK", "[level:20] created new transformer", "[level:30] no matching config-set found, creating a new one", + "[level:20] backporting config", + "[level:20] normalized jest config", "[level:20] loaded module typescript", "[level:20] patching typescript", "[level:20] checking version of typescript: OK", "[level:20] normalized compiler module config via ts-jest option", - "[level:20] backporting config", - "[level:20] normalized jest config", "[level:20] resolved path from babel.config.js to /babel.config.js", "[level:20] normalized babel config via ts-jest option", "[level:20] loaded module babel-jest", diff --git a/src/cli/cli.spec.ts b/src/cli/cli.spec.ts index 08ddd2ef05..d8be66e0cb 100644 --- a/src/cli/cli.spec.ts +++ b/src/cli/cli.spec.ts @@ -66,43 +66,43 @@ describe('cli', () => { it('should output usage', async () => { expect.assertions(2) await expect(runCli()).resolves.toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": "", - "stdout": " -Usage: - ts-jest command [options] [...args] - -Commands: - config:init Creates initial Jest configuration - config:migrate Migrates a given Jest configuration - help [command] Show this help, or help about a command - -Example: - ts-jest help config:migrate -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": "", + "stdout": " + Usage: + ts-jest command [options] [...args] + + Commands: + config:init Creates initial Jest configuration + config:migrate Migrates a given Jest configuration + help [command] Show this help, or help about a command + + Example: + ts-jest help config:migrate + ", + } + `) await expect(runCli('hello:motto')).resolves.toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": "", - "stdout": " -Usage: - ts-jest command [options] [...args] - -Commands: - config:init Creates initial Jest configuration - config:migrate Migrates a given Jest configuration - help [command] Show this help, or help about a command - -Example: - ts-jest help config:migrate -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": "", + "stdout": " + Usage: + ts-jest command [options] [...args] + + Commands: + config:init Creates initial Jest configuration + config:migrate Migrates a given Jest configuration + help [command] Show this help, or help about a command + + Example: + ts-jest help config:migrate + ", + } + `) }) }) @@ -229,31 +229,31 @@ Jest configuration written to "${normalize('/foo/bar/package.json')}". it('should output help', async () => { const res = await runCli('help', noOption[0]) expect(res).toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": "", - "stdout": " -Usage: - ts-jest config:init [options] [] - -Arguments: - Can be a js or json Jest config file. If it is a - package.json file, the configuration will be read from - the \\"jest\\" property. - Default: jest.config.js - -Options: - --force Discard any existing Jest config - --js ts|babel Process .js files with ts-jest if 'ts' or with - babel-jest if 'babel' - --no-jest-preset Disable the use of Jest presets - --tsconfig Path to the tsconfig.json file - --babel Pipe babel-jest after ts-jest - --jsdom Use jsdom as test environment instead of node -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": "", + "stdout": " + Usage: + ts-jest config:init [options] [] + + Arguments: + Can be a js or json Jest config file. If it is a + package.json file, the configuration will be read from + the \\"jest\\" property. + Default: jest.config.js + + Options: + --force Discard any existing Jest config + --js ts|babel Process .js files with ts-jest if 'ts' or with + babel-jest if 'babel' + --no-jest-preset Disable the use of Jest presets + --tsconfig Path to the tsconfig.json file + --babel Pipe babel-jest after ts-jest + --jsdom Use jsdom as test environment instead of node + ", + } + `) }) }) // init @@ -306,30 +306,32 @@ Options: ) const res = await runCli(...noOption, pkgPaths.current) expect(res).toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": " -Migrated Jest configuration: - - -Detected preset 'default' as the best matching preset for your configuration. -Visit https://kulshekhar.github.io/ts-jest/user/config/#jest-preset for more information about presets. - -", - "stdout": "\\"jest\\": { - \\"globals\\": { - \\"ts-jest\\": { - \\"tsConfig\\": { - \\"target\\": \\"es6\\" - } - } - }, - \\"preset\\": \\"ts-jest\\" -} -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": " + Migrated Jest configuration: + + + Detected preset 'default' as the best matching preset for your configuration. + Visit https://kulshekhar.github.io/ts-jest/user/config/#jest-preset for more information about presets. + + ", + "stdout": "\\"jest\\": { + \\"globals\\": { + \\"ts-jest\\": { + \\"tsConfig\\": { + \\"target\\": \\"es6\\" + } + } + }, + \\"testMatch\\": null, + \\"testRegex\\": [], + \\"preset\\": \\"ts-jest\\" + } + ", + } + `) expect(fs.writeFileSync).not.toHaveBeenCalled() }) @@ -345,24 +347,29 @@ Visit https://kulshekhar.github.io/ts-jest/user/config/#jest-preset for more inf ) const res = await runCli(...fullOptions, pkgPaths.current) expect(res).toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": " -Migrated Jest configuration: -", - "stdout": "\\"jest\\": { - \\"globals\\": { - \\"ts-jest\\": { - \\"tsConfig\\": { - \\"target\\": \\"es6\\" - } - } - } -} -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": " + Migrated Jest configuration: + ", + "stdout": "\\"jest\\": { + \\"globals\\": { + \\"ts-jest\\": { + \\"tsConfig\\": { + \\"target\\": \\"es6\\" + } + } + }, + \\"testMatch\\": [ + \\"**/?(*.)+(spec|test).[jt]s?(x)\\", + \\"**/__tests__/**/*.[jt]s?(x)\\" + ], + \\"testRegex\\": [] + } + ", + } + `) expect(fs.writeFileSync).not.toHaveBeenCalled() }) @@ -387,29 +394,25 @@ Migrated Jest configuration: ) const res = await runCli(...noOption, pkgPaths.current) expect(res.stdout).toMatchInlineSnapshot(` -"\\"jest\\": { - \\"globals\\": { - \\"ts-jest\\": { - \\"tsConfig\\": { - \\"target\\": \\"es6\\" - } - } - }, - \\"moduleFileExtensions\\": [ - \\"js\\", - \\"ts\\", - \\"tsx\\" - ], - \\"testMatch\\": [ - \\"**/?(*.)+(spec|test).js?(x)\\", - \\"**/?(*.)+(spec|test).ts?(x)\\", - \\"**/__tests__/**/*.js?(x)\\", - \\"**/__tests__/**/*.ts?(x)\\" - ], - \\"preset\\": \\"ts-jest\\" -} -" -`) + "\\"jest\\": { + \\"globals\\": { + \\"ts-jest\\": { + \\"tsConfig\\": { + \\"target\\": \\"es6\\" + } + } + }, + \\"moduleFileExtensions\\": [ + \\"js\\", + \\"ts\\", + \\"tsx\\" + ], + \\"testMatch\\": null, + \\"testRegex\\": [], + \\"preset\\": \\"ts-jest\\" + } + " + `) }) it('should reset testMatch if testRegex is used', async () => { @@ -426,13 +429,13 @@ Migrated Jest configuration: ) const res = await runCli(...noOption, pkgPaths.current) expect(res.stdout).toMatchInlineSnapshot(` -"\\"jest\\": { - \\"testRegex\\": \\"foo-pattern\\", - \\"preset\\": \\"ts-jest\\", - \\"testMatch\\": null -} -" -`) + "\\"jest\\": { + \\"testRegex\\": \\"foo-pattern\\", + \\"testMatch\\": null, + \\"preset\\": \\"ts-jest\\" + } + " + `) }) it('should detect best preset', async () => { @@ -444,31 +447,37 @@ Migrated Jest configuration: jest.doMock(pkgPaths.nextCfg, () => ({}), { virtual: true }) let res = await runCli(...noOption, pkgPaths.currentCfg) expect(res.stdout).toMatchInlineSnapshot(` -"module.exports = { - preset: 'ts-jest', -} -" -`) + "module.exports = { + testMatch: null, + testRegex: [], + preset: 'ts-jest', + } + " + `) // js-with-ts from args jest.doMock(pkgPaths.nextCfg, () => ({}), { virtual: true }) res = await runCli(...noOption, '--allow-js', pkgPaths.currentCfg) expect(res.stdout).toMatchInlineSnapshot(` -"module.exports = { - preset: 'ts-jest/presets/js-with-ts', -} -" -`) + "module.exports = { + testMatch: null, + testRegex: [], + preset: 'ts-jest/presets/js-with-ts', + } + " + `) // js-with-ts from previous transform jest.doMock(pkgPaths.nextCfg, () => ({ transform: { '^.+\\.[tj]sx?$': 'ts-jest' } }), { virtual: true }) res = await runCli(...noOption, pkgPaths.currentCfg) expect(res.stdout).toMatchInlineSnapshot(` -"module.exports = { - preset: 'ts-jest/presets/js-with-ts', -} -" -`) + "module.exports = { + testMatch: null, + testRegex: [], + preset: 'ts-jest/presets/js-with-ts', + } + " + `) // js-with-babel from previous transform jest.doMock(pkgPaths.nextCfg, () => ({ transform: { '^.+\\.jsx?$': 'babel-jest', '^.+\\.tsx?$': 'ts-jest' } }), { @@ -476,11 +485,13 @@ Migrated Jest configuration: }) res = await runCli(...noOption, pkgPaths.currentCfg) expect(res.stdout).toMatchInlineSnapshot(` -"module.exports = { - preset: 'ts-jest/presets/js-with-babel', -} -" -`) + "module.exports = { + testMatch: null, + testRegex: [], + preset: 'ts-jest/presets/js-with-babel', + } + " + `) // defaults when previous transform is ambiguous jest.doMock( @@ -490,15 +501,17 @@ Migrated Jest configuration: ) res = await runCli(...noOption, pkgPaths.currentCfg) expect(res.stdout).toMatchInlineSnapshot(` -"module.exports = { - transform: { - '^src/js/.+\\\\\\\\.jsx?$': 'babel-jest', - '^src/ts/.+\\\\\\\\.tsx?$': 'ts-jest', - }, - preset: 'ts-jest', -} -" -`) + "module.exports = { + transform: { + '^src/js/.+\\\\\\\\.jsx?$': 'babel-jest', + '^src/ts/.+\\\\\\\\.tsx?$': 'ts-jest', + }, + testMatch: null, + testRegex: [], + preset: 'ts-jest', + } + " + `) }) it('should normalize transform values', async () => { @@ -519,41 +532,43 @@ Migrated Jest configuration: ) const res = await runCli(...noOption, pkgPaths.current) expect(res.stdout).toMatchInlineSnapshot(` -"\\"jest\\": { - \\"transform\\": { - \\"/src/.+\\\\\\\\.[jt]s$\\": \\"ts-jest\\", - \\"foo\\\\\\\\.ts\\": \\"ts-jest\\", - \\"bar\\\\\\\\.ts\\": \\"ts-jest\\" - }, - \\"preset\\": \\"ts-jest\\" -} -" -`) + "\\"jest\\": { + \\"transform\\": { + \\"/src/.+\\\\\\\\.[jt]s$\\": \\"ts-jest\\", + \\"foo\\\\\\\\.ts\\": \\"ts-jest\\", + \\"bar\\\\\\\\.ts\\": \\"ts-jest\\" + }, + \\"testMatch\\": null, + \\"testRegex\\": [], + \\"preset\\": \\"ts-jest\\" + } + " + `) }) it('should output help', async () => { const res = await runCli('help', noOption[0]) expect(res).toMatchInlineSnapshot(` -Object { - "exitCode": 0, - "log": "", - "stderr": "", - "stdout": " -Usage: - ts-jest config:migrate [options] - -Arguments: - Can be a js or json Jest config file. If it is a - package.json file, the configuration will be read from - the \\"jest\\" property. - -Options: - --js ts|babel Process .js files with ts-jest if 'ts' or with - babel-jest if 'babel' - --no-jest-preset Disable the use of Jest presets -", -} -`) + Object { + "exitCode": 0, + "log": "", + "stderr": "", + "stdout": " + Usage: + ts-jest config:migrate [options] + + Arguments: + Can be a js or json Jest config file. If it is a + package.json file, the configuration will be read from + the \\"jest\\" property. + + Options: + --js ts|babel Process .js files with ts-jest if 'ts' or with + babel-jest if 'babel' + --no-jest-preset Disable the use of Jest presets + ", + } + `) }) }) // migrate }) // config diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 57ecf1e96b..bed37f662b 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -173,13 +173,14 @@ export class ConfigSet { tsBuildInfoFile: undefined, } - constructor(private readonly jestConfig: Config.ProjectConfig, private readonly parentLogger?: Logger) { + constructor(jestConfig: Config.ProjectConfig | undefined, private readonly parentLogger?: Logger) { this.logger = this.parentLogger ? this.parentLogger.child({ [LogContexts.namespace]: 'config' }) : rootLogger.child({ namespace: 'config' }) - this.cwd = normalize(this.jestConfig.cwd ?? process.cwd()) - this.rootDir = normalize(this.jestConfig.rootDir ?? this.cwd) - const tsJestCfg = this.jestConfig.globals && this.jestConfig.globals['ts-jest'] + this._backportJestCfg(jestConfig ?? Object.create(null)) + this.cwd = normalize(this._jestCfg.cwd ?? process.cwd()) + this.rootDir = normalize(this._jestCfg.rootDir ?? this.cwd) + const tsJestCfg = this._jestCfg.globals && this._jestCfg.globals['ts-jest'] const options: TsJestGlobalOptions = tsJestCfg ?? Object.create(null) // compiler module this.compilerModule = importer.typescript(ImportReasons.TsJest, options.compiler ?? 'typescript') @@ -188,7 +189,6 @@ export class ConfigSet { this.logger.debug({ compilerModule: this.compilerModule }, 'normalized compiler module config via ts-jest option') - this._backportJestCfg() this._matchablePatterns = [...this._jestCfg.testMatch, ...this._jestCfg.testRegex].filter( (pattern) => /** @@ -210,8 +210,8 @@ export class ConfigSet { /** * @internal */ - private _backportJestCfg(): void { - const config = backportJestConfig(this.logger, this.jestConfig) + private _backportJestCfg(jestCfg: Config.ProjectConfig): void { + const config = backportJestConfig(this.logger, jestCfg) this.logger.debug({ jestConfig: config }, 'normalized jest config') diff --git a/src/types.ts b/src/types.ts index 82c43dde2d..5bcf4ea24f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -155,10 +155,12 @@ export interface TsJestGlobalOptions { stringifyContentPathRegex?: string | RegExp } +/** + * For typings in `jest.config.ts` + */ export interface GlobalConfigTsJest extends Config.ConfigGlobals { 'ts-jest': TsJestGlobalOptions } - export interface InitialOptionsTsJest extends Config.InitialOptions { globals?: GlobalConfigTsJest } diff --git a/src/utils/__snapshots__/backports.spec.ts.snap b/src/utils/__snapshots__/backports.spec.ts.snap index 77d85b21de..e2574c239d 100644 --- a/src/utils/__snapshots__/backports.spec.ts.snap +++ b/src/utils/__snapshots__/backports.spec.ts.snap @@ -13,6 +13,11 @@ Object { "globals": Object { "ts-jest": Object {}, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -40,6 +45,11 @@ Object { "stringifyContentPathRegex": "\\\\.html?$", }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -71,6 +81,11 @@ Object { }, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -103,6 +118,11 @@ Object { }, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -132,6 +152,11 @@ Object { "diagnostics": false, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -163,6 +188,11 @@ Object { }, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -192,6 +222,11 @@ Object { "babelConfig": true, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -219,6 +254,11 @@ Object { "globals": Object { "ts-jest": Object {}, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -248,6 +288,11 @@ Object { "tsConfig": "tsconfig.build.json", }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -277,6 +322,11 @@ Object { "isolatedModules": true, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -306,6 +356,11 @@ Object { "isolatedModules": false, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -335,6 +390,11 @@ Object { "babelConfig": Object {}, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; @@ -365,6 +425,11 @@ Object { "babelConfig": true, }, }, + "testMatch": Array [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)", + ], + "testRegex": Array [], } `; diff --git a/src/utils/backports.ts b/src/utils/backports.ts index dbd87f0a87..9031a68885 100644 --- a/src/utils/backports.ts +++ b/src/utils/backports.ts @@ -2,6 +2,7 @@ import type { Config } from '@jest/types' import { LogContexts, Logger } from 'bs-logger' import { Deprecations, Helps, interpolate } from './messages' +import { DEFAULT_JEST_TEST_MATCH } from '../constants' const context = { [LogContexts.namespace]: 'backports' } @@ -94,6 +95,8 @@ export const backportJestConfig =