Skip to content

Commit

Permalink
feat(jest-config): Throw an error instead of showing a warning if mul…
Browse files Browse the repository at this point in the history
…tiple configs are used
  • Loading branch information
TrickyPi committed Feb 28, 2022
1 parent c2872aa commit fc9bc4f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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))
Expand Down
70 changes: 26 additions & 44 deletions packages/jest-config/src/__tests__/resolveConfigPath.test.ts
Expand Up @@ -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<void, Array<any>>;

// 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));

Expand Down Expand Up @@ -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,
Expand All @@ -81,7 +69,6 @@ describe.each(JEST_CONFIG_EXT_ORDER.slice(0))(

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

mockedConsoleWarn.mockClear();
// absolute
expect(
resolveConfigPath(path.dirname(absolutePackageJsonPath), DIR),
Expand All @@ -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),
Expand All @@ -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(
Expand All @@ -146,8 +120,7 @@ const pickPairsWithSameOrder = <T>(array: ReadonlyArray<T>) =>
.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([
Expand All @@ -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}`,
Expand All @@ -173,15 +144,26 @@ 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);
});
},
);

test('skip multiple config error, if skipMultipleConfigError is true', () => {
const [extension1, extension2] = JEST_CONFIG_EXT_ORDER;
const relativeJestConfigPaths = [
`a/b/c/jest.config${extension1}`,
`a/b/c/jest.config${extension2}`,
];

writeFiles(DIR, {
[relativeJestConfigPaths[0]]: '',
[relativeJestConfigPaths[1]]: '',
});

expect(
resolveConfigPath(path.dirname(relativeJestConfigPaths[0]), DIR, true),
).toBe(path.resolve(DIR, relativeJestConfigPaths[0]));
});
6 changes: 3 additions & 3 deletions packages/jest-config/src/index.ts
Expand Up @@ -41,7 +41,7 @@ export async function readConfig(
skipArgvConfigOption?: boolean,
parentConfigDirname?: string | null,
projectIndex = Infinity,
skipMultipleConfigWarning = false,
skipMultipleConfigError = false,
): Promise<ReadConfig> {
let rawOptions: Config.InitialOptions;
let configPath = null;
Expand Down Expand Up @@ -78,15 +78,15 @@ export async function readConfig(
configPath = resolveConfigPath(
argv.config,
process.cwd(),
skipMultipleConfigWarning,
skipMultipleConfigError,
);
rawOptions = await readConfigFileAndSetRootDir(configPath);
} else {
// Otherwise just try to find config in the current rootDir.
configPath = resolveConfigPath(
packageRootOrConfig,
process.cwd(),
skipMultipleConfigWarning,
skipMultipleConfigError,
);
rawOptions = await readConfigFileAndSetRootDir(configPath);
}
Expand Down
44 changes: 21 additions & 23 deletions packages/jest-config/src/resolveConfigPath.ts
Expand Up @@ -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}`);
Expand Down Expand Up @@ -58,15 +58,15 @@ export default function resolveConfigPath(
absolutePath,
pathToResolve,
cwd,
skipMultipleConfigWarning,
skipMultipleConfigError,
);
}

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)),
Expand All @@ -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) {
Expand All @@ -96,7 +96,7 @@ const resolveConfigPathByTraversing = (
path.dirname(pathToResolve),
initialPath,
cwd,
skipMultipleConfigWarning,
skipMultipleConfigError,
);
};

Expand Down Expand Up @@ -137,20 +137,18 @@ function extraIfPackageJson(configPath: string) {
return '';
}

const makeMultipleConfigsWarning = (configPaths: Array<string>) =>
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<string>) =>
[
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');

0 comments on commit fc9bc4f

Please sign in to comment.