Skip to content

Commit 83e9127

Browse files
committed
feat(jest-config): Throw an error instead of showing a warning if multiple configs are used
1 parent c2872aa commit 83e9127

File tree

6 files changed

+48
-94
lines changed

6 files changed

+48
-94
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Features
44

5+
- `[jest-config]` Throw an error instead of showing a warning if multiple configs are used ([#12506](https://github.com/facebook/jest/pull/12506))
56
- `[babel-jest]` Export `createTransformer` function ([#12399](https://github.com/facebook/jest/pull/12399))
67
- `[expect]` Expose `AsymmetricMatchers`, `MatcherFunction` and `MatcherFunctionWithState` interfaces ([#12363](https://github.com/facebook/jest/pull/12363), [#12376](https://github.com/facebook/jest/pull/12376))
78
- `[jest-circus, jest-jasmine2]` Allowed classes and functions as `describe` and `it`/`test` names ([#12484](https://github.com/facebook/jest/pull/12484))
Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`multiple configs will warn 1`] = `
4-
"● Multiple configurations found:
3+
exports[`multiple configs will throw error 1`] = `
4+
"Error: ● Multiple configurations found:
55
* <rootDir>/e2e/multiple-configs/jest.config.js
66
* <rootDir>/e2e/multiple-configs/jest.config.json
77
* \`jest\` key in <rootDir>/e2e/multiple-configs/package.json
@@ -12,14 +12,10 @@ exports[`multiple configs will warn 1`] = `
1212
Configuration Documentation:
1313
https://jestjs.io/docs/configuration.html
1414
15-
PASS Config from js file __tests__/test.js
16-
✓ dummy test"
17-
`;
18-
19-
exports[`multiple configs will warn 2`] = `
20-
"Test Suites: 1 passed, 1 total
21-
Tests: 1 passed, 1 total
22-
Snapshots: 0 total
23-
Time: <<REPLACED>>
24-
Ran all test suites."
25-
`;
15+
at resolveConfigPathByTraversing (<rootDir>/packages/jest-config/build/resolveConfigPath.js:166:11)
16+
at resolveConfigPath (<rootDir>/packages/jest-config/build/resolveConfigPath.js:141:10)
17+
at readConfig (<rootDir>/packages/jest-config/build/index.js:211:49)
18+
at readConfigs (<rootDir>/packages/jest-config/build/index.js:403:32)
19+
at runCLI (<rootDir>/packages/jest-core/build/cli/index.js:133:29)
20+
at Object.run (<rootDir>/packages/jest-cli/build/cli/index.js:155:62)"
21+
`;

e2e/__tests__/multipleConfigs.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,30 @@
77

88
import * as path from 'path';
99
import slash = require('slash');
10-
import {extractSummary} from '../Utils';
1110
import runJest from '../runJest';
1211

1312
const MULTIPLE_CONFIGS_WARNING_TEXT = 'Multiple configurations found';
1413

15-
test('multiple configs will warn', () => {
14+
test('multiple configs will throw error', () => {
1615
const rootDir = slash(path.resolve(__dirname, '../..'));
1716
const {exitCode, stderr} = runJest('multiple-configs', [], {
1817
skipPkgJsonCheck: true,
1918
});
2019

21-
expect(exitCode).toBe(0);
20+
expect(exitCode).toBe(1);
2221
expect(stderr).toContain(MULTIPLE_CONFIGS_WARNING_TEXT);
2322

2423
const cleanStdErr = stderr.replace(new RegExp(rootDir, 'g'), '<rootDir>');
25-
const {rest, summary} = extractSummary(cleanStdErr);
26-
27-
expect(rest).toMatchSnapshot();
28-
expect(summary).toMatchSnapshot();
24+
expect(cleanStdErr).toMatchSnapshot();
2925
});
3026

31-
test('multiple configs warning can be suppressed by using --config', () => {
32-
const {exitCode, stderr} = runJest(
27+
test('multiple configs error can be suppressed by using --config', () => {
28+
const {exitCode} = runJest(
3329
'multiple-configs',
3430
['--config', 'jest.config.json'],
3531
{
3632
skipPkgJsonCheck: true,
3733
},
3834
);
39-
4035
expect(exitCode).toBe(0);
41-
expect(stderr).not.toContain(MULTIPLE_CONFIGS_WARNING_TEXT);
4236
});

packages/jest-config/src/__tests__/resolveConfigPath.test.ts

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ const ERROR_PATTERN = /Could not find a config file based on provided values/;
1616
const NO_ROOT_DIR_ERROR_PATTERN = /Can't find a root directory/;
1717
const MULTIPLE_CONFIGS_ERROR_PATTERN = /Multiple configurations found/;
1818

19-
const mockConsoleWarn = () => {
20-
jest.spyOn(console, 'warn');
21-
const mockedConsoleWarn = console.warn as jest.Mock<void, Array<any>>;
22-
23-
// We will mock console.warn because it would produce a lot of noise in the tests
24-
mockedConsoleWarn.mockImplementation(() => {});
25-
26-
return mockedConsoleWarn;
27-
};
28-
2919
beforeEach(() => cleanup(DIR));
3020
afterEach(() => cleanup(DIR));
3121

@@ -56,8 +46,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))(
5646
});
5747

5848
test(`directory path with "${extension}"`, () => {
59-
const mockedConsoleWarn = mockConsoleWarn();
60-
6149
const relativePackageJsonPath = 'a/b/c/package.json';
6250
const absolutePackageJsonPath = path.resolve(
6351
DIR,
@@ -81,7 +69,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))(
8169

8270
writeFiles(DIR, {[relativePackageJsonPath]: ''});
8371

84-
mockedConsoleWarn.mockClear();
8572
// absolute
8673
expect(
8774
resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR),
@@ -91,12 +78,10 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))(
9178
expect(
9279
resolveConfigPath(path.dirname(relativePackageJsonPath), DIR),
9380
).toBe(absolutePackageJsonPath);
94-
expect(mockedConsoleWarn).not.toBeCalled();
9581

9682
// jest.config.js takes precedence
9783
writeFiles(DIR, {[relativeJestConfigPath]: ''});
9884

99-
mockedConsoleWarn.mockClear();
10085
// absolute
10186
expect(
10287
resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR),
@@ -106,30 +91,19 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))(
10691
expect(
10792
resolveConfigPath(path.dirname(relativePackageJsonPath), DIR),
10893
).toBe(absoluteJestConfigPath);
109-
expect(mockedConsoleWarn).not.toBeCalled();
11094

11195
// jest.config.js and package.json with 'jest' cannot be used together
11296
writeFiles(DIR, {[relativePackageJsonPath]: JSON.stringify({jest: {}})});
11397

11498
// absolute
115-
mockedConsoleWarn.mockClear();
116-
expect(
99+
expect(() =>
117100
resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR),
118-
).toBe(absoluteJestConfigPath);
119-
expect(mockedConsoleWarn).toBeCalledTimes(1);
120-
expect(mockedConsoleWarn.mock.calls[0].join()).toMatch(
121-
MULTIPLE_CONFIGS_ERROR_PATTERN,
122-
);
101+
).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN);
123102

124103
// relative
125-
mockedConsoleWarn.mockClear();
126-
expect(
104+
expect(() =>
127105
resolveConfigPath(path.dirname(relativePackageJsonPath), DIR),
128-
).toBe(absoluteJestConfigPath);
129-
expect(mockedConsoleWarn).toBeCalledTimes(1);
130-
expect(mockedConsoleWarn.mock.calls[0].join()).toMatch(
131-
MULTIPLE_CONFIGS_ERROR_PATTERN,
132-
);
106+
).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN);
133107

134108
expect(() => {
135109
resolveConfigPath(
@@ -146,8 +120,7 @@ const pickPairsWithSameOrder = <T>(array: ReadonlyArray<T>) =>
146120
.map((value1, idx, arr) =>
147121
arr.slice(idx + 1).map(value2 => [value1, value2]),
148122
)
149-
// TODO: use .flat() when we drop Node 10
150-
.reduce((acc, val) => acc.concat(val), []);
123+
.flat();
151124

152125
test('pickPairsWithSameOrder', () => {
153126
expect(pickPairsWithSameOrder([1, 2, 3])).toStrictEqual([
@@ -158,11 +131,9 @@ test('pickPairsWithSameOrder', () => {
158131
});
159132

160133
describe.each(pickPairsWithSameOrder(JEST_CONFIG_EXT_ORDER))(
161-
'Using multiple configs shows warning',
134+
'Using multiple configs shows error',
162135
(extension1, extension2) => {
163-
test(`Using jest.config${extension1} and jest.config${extension2} shows warning`, () => {
164-
const mockedConsoleWarn = mockConsoleWarn();
165-
136+
test(`Using jest.config${extension1} and jest.config${extension2} shows error`, () => {
166137
const relativeJestConfigPaths = [
167138
`a/b/c/jest.config${extension1}`,
168139
`a/b/c/jest.config${extension2}`,
@@ -173,15 +144,9 @@ describe.each(pickPairsWithSameOrder(JEST_CONFIG_EXT_ORDER))(
173144
[relativeJestConfigPaths[1]]: '',
174145
});
175146

176-
// multiple configs here, should print warning
177-
mockedConsoleWarn.mockClear();
178-
expect(
147+
expect(() =>
179148
resolveConfigPath(path.dirname(relativeJestConfigPaths[0]), DIR),
180-
).toBe(path.resolve(DIR, relativeJestConfigPaths[0]));
181-
expect(mockedConsoleWarn).toBeCalledTimes(1);
182-
expect(mockedConsoleWarn.mock.calls[0].join()).toMatch(
183-
MULTIPLE_CONFIGS_ERROR_PATTERN,
184-
);
149+
).toThrowError(MULTIPLE_CONFIGS_ERROR_PATTERN);
185150
});
186151
},
187152
);

packages/jest-config/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export async function readConfig(
4141
skipArgvConfigOption?: boolean,
4242
parentConfigDirname?: string | null,
4343
projectIndex = Infinity,
44-
skipMultipleConfigWarning = false,
44+
skipMultipleConfigError = false,
4545
): Promise<ReadConfig> {
4646
let rawOptions: Config.InitialOptions;
4747
let configPath = null;
@@ -78,15 +78,15 @@ export async function readConfig(
7878
configPath = resolveConfigPath(
7979
argv.config,
8080
process.cwd(),
81-
skipMultipleConfigWarning,
81+
skipMultipleConfigError,
8282
);
8383
rawOptions = await readConfigFileAndSetRootDir(configPath);
8484
} else {
8585
// Otherwise just try to find config in the current rootDir.
8686
configPath = resolveConfigPath(
8787
packageRootOrConfig,
8888
process.cwd(),
89-
skipMultipleConfigWarning,
89+
skipMultipleConfigError,
9090
);
9191
rawOptions = await readConfigFileAndSetRootDir(configPath);
9292
}

packages/jest-config/src/resolveConfigPath.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const getConfigFilename = (ext: string) => JEST_CONFIG_BASE_NAME + ext;
2323
export default function resolveConfigPath(
2424
pathToResolve: string,
2525
cwd: string,
26-
skipMultipleConfigWarning = false,
26+
skipMultipleConfigError = false,
2727
): string {
2828
if (!path.isAbsolute(cwd)) {
2929
throw new Error(`"cwd" must be an absolute path. cwd: ${cwd}`);
@@ -58,15 +58,15 @@ export default function resolveConfigPath(
5858
absolutePath,
5959
pathToResolve,
6060
cwd,
61-
skipMultipleConfigWarning,
61+
skipMultipleConfigError,
6262
);
6363
}
6464

6565
const resolveConfigPathByTraversing = (
6666
pathToResolve: string,
6767
initialPath: string,
6868
cwd: string,
69-
skipMultipleConfigWarning: boolean,
69+
skipMultipleConfigError: boolean,
7070
): string => {
7171
const configFiles = JEST_CONFIG_EXT_ORDER.map(ext =>
7272
path.resolve(pathToResolve, getConfigFilename(ext)),
@@ -77,8 +77,8 @@ const resolveConfigPathByTraversing = (
7777
configFiles.push(packageJson);
7878
}
7979

80-
if (!skipMultipleConfigWarning && configFiles.length > 1) {
81-
console.warn(makeMultipleConfigsWarning(configFiles));
80+
if (!skipMultipleConfigError && configFiles.length > 1) {
81+
throw new Error(makeMultipleConfigsErrorMessage(configFiles));
8282
}
8383

8484
if (configFiles.length > 0 || packageJson) {
@@ -96,7 +96,7 @@ const resolveConfigPathByTraversing = (
9696
path.dirname(pathToResolve),
9797
initialPath,
9898
cwd,
99-
skipMultipleConfigWarning,
99+
skipMultipleConfigError,
100100
);
101101
};
102102

@@ -137,20 +137,18 @@ function extraIfPackageJson(configPath: string) {
137137
return '';
138138
}
139139

140-
const makeMultipleConfigsWarning = (configPaths: Array<string>) =>
141-
chalk.yellow(
142-
[
143-
chalk.bold('\u25cf Multiple configurations found:'),
144-
...configPaths.map(
145-
configPath =>
146-
` * ${extraIfPackageJson(configPath)}${slash(configPath)}`,
147-
),
148-
'',
149-
' Implicit config resolution does not allow multiple configuration files.',
150-
' Either remove unused config files or select one explicitly with `--config`.',
151-
'',
152-
' Configuration Documentation:',
153-
' https://jestjs.io/docs/configuration.html',
154-
'',
155-
].join('\n'),
156-
);
140+
const makeMultipleConfigsErrorMessage = (configPaths: Array<string>) =>
141+
[
142+
chalk.bold('\u25cf Multiple configurations found:'),
143+
...configPaths.map(
144+
configPath =>
145+
` * ${extraIfPackageJson(configPath)}${slash(configPath)}`,
146+
),
147+
'',
148+
' Implicit config resolution does not allow multiple configuration files.',
149+
' Either remove unused config files or select one explicitly with `--config`.',
150+
'',
151+
' Configuration Documentation:',
152+
' https://jestjs.io/docs/configuration.html',
153+
'',
154+
].join('\n');

0 commit comments

Comments
 (0)