From 83e91279fde3ca87b4f02cb8a744b62a26c47d11 Mon Sep 17 00:00:00 2001 From: TrickyPi <530257315@qq.com> Date: Mon, 28 Feb 2022 13:42:09 +0800 Subject: [PATCH] feat(jest-config): Throw an error instead of showing a warning if multiple configs are used --- CHANGELOG.md | 1 + .../__snapshots__/multipleConfigs.ts.snap | 22 ++++---- e2e/__tests__/multipleConfigs.ts | 16 ++---- .../src/__tests__/resolveConfigPath.test.ts | 53 ++++--------------- packages/jest-config/src/index.ts | 6 +-- packages/jest-config/src/resolveConfigPath.ts | 44 ++++++++------- 6 files changed, 48 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1f622dc41e6..1a4dcedbd1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-config]` Throw an error instead of showing a warning if multiple configs are used ([#12506](https://github.com/facebook/jest/pull/12506)) - `[babel-jest]` Export `createTransformer` function ([#12399](https://github.com/facebook/jest/pull/12399)) - `[expect]` Expose `AsymmetricMatchers`, `MatcherFunction` and `MatcherFunctionWithState` interfaces ([#12363](https://github.com/facebook/jest/pull/12363), [#12376](https://github.com/facebook/jest/pull/12376)) - `[jest-circus, jest-jasmine2]` Allowed classes and functions as `describe` and `it`/`test` names ([#12484](https://github.com/facebook/jest/pull/12484)) diff --git a/e2e/__tests__/__snapshots__/multipleConfigs.ts.snap b/e2e/__tests__/__snapshots__/multipleConfigs.ts.snap index 3805df0c73fb..f86f030a4ab4 100644 --- a/e2e/__tests__/__snapshots__/multipleConfigs.ts.snap +++ b/e2e/__tests__/__snapshots__/multipleConfigs.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`multiple configs will warn 1`] = ` -"● Multiple configurations found: +exports[`multiple configs will throw error 1`] = ` +"Error: ● Multiple configurations found: * /e2e/multiple-configs/jest.config.js * /e2e/multiple-configs/jest.config.json * \`jest\` key in /e2e/multiple-configs/package.json @@ -12,14 +12,10 @@ exports[`multiple configs will warn 1`] = ` Configuration Documentation: https://jestjs.io/docs/configuration.html -PASS Config from js file __tests__/test.js - ✓ dummy test" -`; - -exports[`multiple configs will warn 2`] = ` -"Test Suites: 1 passed, 1 total -Tests: 1 passed, 1 total -Snapshots: 0 total -Time: <> -Ran all test suites." -`; + at resolveConfigPathByTraversing (/packages/jest-config/build/resolveConfigPath.js:166:11) + at resolveConfigPath (/packages/jest-config/build/resolveConfigPath.js:141:10) + at readConfig (/packages/jest-config/build/index.js:211:49) + at readConfigs (/packages/jest-config/build/index.js:403:32) + at runCLI (/packages/jest-core/build/cli/index.js:133:29) + at Object.run (/packages/jest-cli/build/cli/index.js:155:62)" +`; \ No newline at end of file diff --git a/e2e/__tests__/multipleConfigs.ts b/e2e/__tests__/multipleConfigs.ts index 84644f94a59f..bf5a71a1dadb 100644 --- a/e2e/__tests__/multipleConfigs.ts +++ b/e2e/__tests__/multipleConfigs.ts @@ -7,36 +7,30 @@ import * as path from 'path'; import slash = require('slash'); -import {extractSummary} from '../Utils'; import runJest from '../runJest'; const MULTIPLE_CONFIGS_WARNING_TEXT = 'Multiple configurations found'; -test('multiple configs will warn', () => { +test('multiple configs will throw error', () => { const rootDir = slash(path.resolve(__dirname, '../..')); const {exitCode, stderr} = runJest('multiple-configs', [], { skipPkgJsonCheck: true, }); - expect(exitCode).toBe(0); + expect(exitCode).toBe(1); expect(stderr).toContain(MULTIPLE_CONFIGS_WARNING_TEXT); const cleanStdErr = stderr.replace(new RegExp(rootDir, 'g'), ''); - const {rest, summary} = extractSummary(cleanStdErr); - - expect(rest).toMatchSnapshot(); - expect(summary).toMatchSnapshot(); + expect(cleanStdErr).toMatchSnapshot(); }); -test('multiple configs warning can be suppressed by using --config', () => { - const {exitCode, stderr} = runJest( +test('multiple configs error can be suppressed by using --config', () => { + const {exitCode} = runJest( 'multiple-configs', ['--config', 'jest.config.json'], { skipPkgJsonCheck: true, }, ); - expect(exitCode).toBe(0); - expect(stderr).not.toContain(MULTIPLE_CONFIGS_WARNING_TEXT); }); diff --git a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts index 96db06c9213b..167ab607bb31 100644 --- a/packages/jest-config/src/__tests__/resolveConfigPath.test.ts +++ b/packages/jest-config/src/__tests__/resolveConfigPath.test.ts @@ -16,16 +16,6 @@ const ERROR_PATTERN = /Could not find a config file based on provided values/; const NO_ROOT_DIR_ERROR_PATTERN = /Can't find a root directory/; const MULTIPLE_CONFIGS_ERROR_PATTERN = /Multiple configurations found/; -const mockConsoleWarn = () => { - jest.spyOn(console, 'warn'); - const mockedConsoleWarn = console.warn as jest.Mock>; - - // We will mock console.warn because it would produce a lot of noise in the tests - mockedConsoleWarn.mockImplementation(() => {}); - - return mockedConsoleWarn; -}; - beforeEach(() => cleanup(DIR)); afterEach(() => cleanup(DIR)); @@ -56,8 +46,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( }); test(`directory path with "${extension}"`, () => { - const mockedConsoleWarn = mockConsoleWarn(); - const relativePackageJsonPath = 'a/b/c/package.json'; const absolutePackageJsonPath = path.resolve( DIR, @@ -81,7 +69,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( writeFiles(DIR, {[relativePackageJsonPath]: ''}); - mockedConsoleWarn.mockClear(); // absolute expect( resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), @@ -91,12 +78,10 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( expect( resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), ).toBe(absolutePackageJsonPath); - expect(mockedConsoleWarn).not.toBeCalled(); // jest.config.js takes precedence writeFiles(DIR, {[relativeJestConfigPath]: ''}); - mockedConsoleWarn.mockClear(); // absolute expect( resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), @@ -106,30 +91,19 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))( expect( resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), ).toBe(absoluteJestConfigPath); - expect(mockedConsoleWarn).not.toBeCalled(); // jest.config.js and package.json with 'jest' cannot be used together writeFiles(DIR, {[relativePackageJsonPath]: JSON.stringify({jest: {}})}); // absolute - mockedConsoleWarn.mockClear(); - expect( + expect(() => resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR), - ).toBe(absoluteJestConfigPath); - expect(mockedConsoleWarn).toBeCalledTimes(1); - expect(mockedConsoleWarn.mock.calls[0].join()).toMatch( - MULTIPLE_CONFIGS_ERROR_PATTERN, - ); + ).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN); // relative - mockedConsoleWarn.mockClear(); - expect( + expect(() => resolveConfigPath(path.dirname(relativePackageJsonPath), DIR), - ).toBe(absoluteJestConfigPath); - expect(mockedConsoleWarn).toBeCalledTimes(1); - expect(mockedConsoleWarn.mock.calls[0].join()).toMatch( - MULTIPLE_CONFIGS_ERROR_PATTERN, - ); + ).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN); expect(() => { resolveConfigPath( @@ -146,8 +120,7 @@ const pickPairsWithSameOrder = (array: ReadonlyArray) => .map((value1, idx, arr) => arr.slice(idx + 1).map(value2 => [value1, value2]), ) - // TODO: use .flat() when we drop Node 10 - .reduce((acc, val) => acc.concat(val), []); + .flat(); test('pickPairsWithSameOrder', () => { expect(pickPairsWithSameOrder([1, 2, 3])).toStrictEqual([ @@ -158,11 +131,9 @@ test('pickPairsWithSameOrder', () => { }); describe.each(pickPairsWithSameOrder(JEST_CONFIG_EXT_ORDER))( - 'Using multiple configs shows warning', + 'Using multiple configs shows error', (extension1, extension2) => { - test(`Using jest.config${extension1} and jest.config${extension2} shows warning`, () => { - const mockedConsoleWarn = mockConsoleWarn(); - + test(`Using jest.config${extension1} and jest.config${extension2} shows error`, () => { const relativeJestConfigPaths = [ `a/b/c/jest.config${extension1}`, `a/b/c/jest.config${extension2}`, @@ -173,15 +144,9 @@ describe.each(pickPairsWithSameOrder(JEST_CONFIG_EXT_ORDER))( [relativeJestConfigPaths[1]]: '', }); - // multiple configs here, should print warning - mockedConsoleWarn.mockClear(); - expect( + expect(() => resolveConfigPath(path.dirname(relativeJestConfigPaths[0]), DIR), - ).toBe(path.resolve(DIR, relativeJestConfigPaths[0])); - expect(mockedConsoleWarn).toBeCalledTimes(1); - expect(mockedConsoleWarn.mock.calls[0].join()).toMatch( - MULTIPLE_CONFIGS_ERROR_PATTERN, - ); + ).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN); }); }, ); diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 1146e84b11b5..1e1448bdf285 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -41,7 +41,7 @@ export async function readConfig( skipArgvConfigOption?: boolean, parentConfigDirname?: string | null, projectIndex = Infinity, - skipMultipleConfigWarning = false, + skipMultipleConfigError = false, ): Promise { let rawOptions: Config.InitialOptions; let configPath = null; @@ -78,7 +78,7 @@ export async function readConfig( configPath = resolveConfigPath( argv.config, process.cwd(), - skipMultipleConfigWarning, + skipMultipleConfigError, ); rawOptions = await readConfigFileAndSetRootDir(configPath); } else { @@ -86,7 +86,7 @@ export async function readConfig( configPath = resolveConfigPath( packageRootOrConfig, process.cwd(), - skipMultipleConfigWarning, + skipMultipleConfigError, ); rawOptions = await readConfigFileAndSetRootDir(configPath); } diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index e513340fb5dd..80e90d2f852e 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -23,7 +23,7 @@ const getConfigFilename = (ext: string) => JEST_CONFIG_BASE_NAME + ext; export default function resolveConfigPath( pathToResolve: string, cwd: string, - skipMultipleConfigWarning = false, + skipMultipleConfigError = false, ): string { if (!path.isAbsolute(cwd)) { throw new Error(`"cwd" must be an absolute path. cwd: ${cwd}`); @@ -58,7 +58,7 @@ export default function resolveConfigPath( absolutePath, pathToResolve, cwd, - skipMultipleConfigWarning, + skipMultipleConfigError, ); } @@ -66,7 +66,7 @@ const resolveConfigPathByTraversing = ( pathToResolve: string, initialPath: string, cwd: string, - skipMultipleConfigWarning: boolean, + skipMultipleConfigError: boolean, ): string => { const configFiles = JEST_CONFIG_EXT_ORDER.map(ext => path.resolve(pathToResolve, getConfigFilename(ext)), @@ -77,8 +77,8 @@ const resolveConfigPathByTraversing = ( configFiles.push(packageJson); } - if (!skipMultipleConfigWarning && configFiles.length > 1) { - console.warn(makeMultipleConfigsWarning(configFiles)); + if (!skipMultipleConfigError && configFiles.length > 1) { + throw new Error(makeMultipleConfigsErrorMessage(configFiles)); } if (configFiles.length > 0 || packageJson) { @@ -96,7 +96,7 @@ const resolveConfigPathByTraversing = ( path.dirname(pathToResolve), initialPath, cwd, - skipMultipleConfigWarning, + skipMultipleConfigError, ); }; @@ -137,20 +137,18 @@ function extraIfPackageJson(configPath: string) { return ''; } -const makeMultipleConfigsWarning = (configPaths: Array) => - chalk.yellow( - [ - chalk.bold('\u25cf Multiple configurations found:'), - ...configPaths.map( - configPath => - ` * ${extraIfPackageJson(configPath)}${slash(configPath)}`, - ), - '', - ' Implicit config resolution does not allow multiple configuration files.', - ' Either remove unused config files or select one explicitly with `--config`.', - '', - ' Configuration Documentation:', - ' https://jestjs.io/docs/configuration.html', - '', - ].join('\n'), - ); +const makeMultipleConfigsErrorMessage = (configPaths: Array) => + [ + chalk.bold('\u25cf Multiple configurations found:'), + ...configPaths.map( + configPath => + ` * ${extraIfPackageJson(configPath)}${slash(configPath)}`, + ), + '', + ' Implicit config resolution does not allow multiple configuration files.', + ' Either remove unused config files or select one explicitly with `--config`.', + '', + ' Configuration Documentation:', + ' https://jestjs.io/docs/configuration.html', + '', + ].join('\n');