Skip to content

Commit e818dca

Browse files
authoredJan 21, 2020
feat: add support for .mjs config (#9431)
1 parent 8236779 commit e818dca

File tree

29 files changed

+284
-130
lines changed

29 files changed

+284
-130
lines changed
 

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- `[jest-config]` [**BREAKING**] Set default display name color based on runner ([#8689](https://github.com/facebook/jest/pull/8689))
1313
- `[jest-config]` Merge preset globals with project globals ([#9027](https://github.com/facebook/jest/pull/9027))
1414
- `[jest-config]` Support `.cjs` config files ([#9291](https://github.com/facebook/jest/pull/9291))
15+
- `[jest-config]` [**BREAKING**] Support `.mjs` config files ([#9431](https://github.com/facebook/jest/pull/9431))
1516
- `[jest-core]` Support reporters as default exports ([#9161](https://github.com/facebook/jest/pull/9161))
1617
- `[jest-core]` Support `--findRelatedTests` paths case insensitivity on Windows ([#8900](https://github.com/facebook/jest/issues/8900))
1718
- `[jest-diff]` Add options for colors and symbols ([#8841](https://github.com/facebook/jest/pull/8841))

‎babel.config.js

+16
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ module.exports = {
1919
presets: ['@babel/preset-typescript'],
2020
test: /\.tsx?$/,
2121
},
22+
// we want this file to keep `import()`, so exclude the transform for it
23+
{
24+
plugins: ['@babel/plugin-syntax-dynamic-import'],
25+
presets: [
26+
'@babel/preset-typescript',
27+
[
28+
'@babel/preset-env',
29+
{
30+
exclude: ['@babel/plugin-proposal-dynamic-import'],
31+
shippedProposals: true,
32+
targets: {node: 8},
33+
},
34+
],
35+
],
36+
test: 'packages/jest-config/src/importMjs.ts',
37+
},
2238
],
2339
plugins: [
2440
['@babel/plugin-transform-modules-commonjs', {allowTopLevelThis: true}],

‎docs/Configuration.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ id: configuration
33
title: Configuring Jest
44
---
55

6-
Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js` file or through the `--config <path/to/file.js|cjs|json>` option. If you'd like to use your `package.json` to store Jest's config, the "jest" key should be used on the top level so Jest will know how to find your settings:
6+
Jest's configuration can be defined in the `package.json` file of your project, or through a `jest.config.js` file or through the `--config <path/to/file.js|cjs|mjs|json>` option. If you'd like to use your `package.json` to store Jest's config, the `"jest"` key should be used on the top level so Jest will know how to find your settings:
77

88
```json
99
{

‎e2e/__tests__/cjsConfigFile.test.ts

-21
This file was deleted.

‎e2e/__tests__/esmConfigFile.test.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import {onNodeVersions} from '@jest/test-utils';
9+
import {json as runWithJson} from '../runJest';
10+
11+
test('reads config from cjs file', () => {
12+
const {json, exitCode} = runWithJson('esm-config/cjs', ['--show-config'], {
13+
skipPkgJsonCheck: true,
14+
});
15+
16+
expect(exitCode).toBe(0);
17+
expect(json.configs).toHaveLength(1);
18+
expect(json.configs[0].displayName).toEqual({
19+
color: 'white',
20+
name: 'Config from cjs file',
21+
});
22+
});
23+
24+
// not unflagged for other versions yet. Update this range if that changes
25+
onNodeVersions('^13.2.0', () => {
26+
test('reads config from mjs file', () => {
27+
const {json, exitCode} = runWithJson('esm-config/mjs', ['--show-config'], {
28+
skipPkgJsonCheck: true,
29+
});
30+
31+
expect(exitCode).toBe(0);
32+
expect(json.configs).toHaveLength(1);
33+
expect(json.configs[0].displayName).toEqual({
34+
color: 'white',
35+
name: 'Config from mjs file',
36+
});
37+
});
38+
});
File renamed without changes.
File renamed without changes.
File renamed without changes.

‎e2e/esm-config/mjs/__tests__/test.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
test('dummy test', () => {
9+
expect(1).toBe(1);
10+
});

‎e2e/esm-config/mjs/jest.config.mjs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export default {
9+
displayName: 'Config from mjs file',
10+
testEnvironment: 'node',
11+
};

‎e2e/esm-config/mjs/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"jest": {}
3+
}

‎packages/jest-cli/src/init/__tests__/__snapshots__/init.test.js.snap

+9
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ Object {
3636
}
3737
`;
3838

39+
exports[`init has-jest-config-file-mjs ask the user whether to override config or not user answered with "Yes" 1`] = `
40+
Object {
41+
"initial": true,
42+
"message": "It seems that you already have a jest configuration, do you want to override it?",
43+
"name": "continue",
44+
"type": "confirm",
45+
}
46+
`;
47+
3948
exports[`init project with package.json and no jest config all questions answered with answer: "No" should return the default configuration (an empty config) 1`] = `
4049
"// For a detailed explanation regarding each configuration property, visit:
4150
// https://jestjs.io/docs/en/configuration.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export default {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "type_module",
3+
"scripts": {
4+
"test": "different-test-runner"
5+
},
6+
"type": "module"
7+
}

‎packages/jest-cli/src/init/__tests__/init.test.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
import * as fs from 'fs';
1010
import * as path from 'path';
1111
import prompts from 'prompts';
12+
import {constants} from 'jest-config';
1213
import init from '../';
13-
import {JEST_CONFIG_EXT_ORDER} from '../constants';
14+
import {onNodeVersions} from '@jest/test-utils';
15+
16+
const {JEST_CONFIG_EXT_ORDER} = constants;
1417

1518
jest.mock('prompts');
1619
jest.mock('../../../../jest-config/build/getCacheDirectory', () => () =>
@@ -52,6 +55,22 @@ describe('init', () => {
5255

5356
expect(evaluatedConfig).toEqual({});
5457
});
58+
59+
onNodeVersions('^13.2.0', () => {
60+
it('should generate empty config with mjs extension', async () => {
61+
prompts.mockReturnValueOnce({});
62+
63+
await init(resolveFromFixture('type_module'));
64+
65+
const writtenJestConfigFilename = fs.writeFileSync.mock.calls[0][0];
66+
const writtenJestConfig = fs.writeFileSync.mock.calls[0][1];
67+
68+
expect(writtenJestConfigFilename.endsWith('.mjs')).toBe(true);
69+
70+
expect(typeof writtenJestConfig).toBe('string');
71+
expect(writtenJestConfig.split('\n')[3]).toBe('export default {');
72+
});
73+
});
5574
});
5675

5776
describe('some questions answered with answer: "Yes"', () => {

‎packages/jest-cli/src/init/constants.ts

-17
This file was deleted.

‎packages/jest-cli/src/init/generate_config_file.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ const stringifyOption = (
3131
);
3232
};
3333

34-
const generateConfigFile = (results: Record<string, unknown>): string => {
34+
const generateConfigFile = (
35+
results: Record<string, unknown>,
36+
generateEsm = false,
37+
): string => {
3538
const {coverage, clearMocks, environment} = results;
3639

3740
const overrides: Record<string, any> = {};
@@ -75,7 +78,7 @@ const generateConfigFile = (results: Record<string, unknown>): string => {
7578
return (
7679
'// For a detailed explanation regarding each configuration property, visit:\n' +
7780
'// https://jestjs.io/docs/en/configuration.html\n\n' +
78-
'module.exports = {\n' +
81+
(generateEsm ? 'export default {\n' : 'module.exports = {\n') +
7982
properties.join('\n') +
8083
'};\n'
8184
);

‎packages/jest-cli/src/init/index.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ import * as path from 'path';
1010
import chalk = require('chalk');
1111
import prompts = require('prompts');
1212
import {sync as realpath} from 'realpath-native';
13+
import {constants} from 'jest-config';
1314
import defaultQuestions, {testScriptQuestion} from './questions';
1415
import {MalformedPackageJsonError, NotFoundPackageJsonError} from './errors';
15-
import {
16+
import generateConfigFile from './generate_config_file';
17+
import modifyPackageJson from './modify_package_json';
18+
import {ProjectPackageJson} from './types';
19+
20+
const {
1621
JEST_CONFIG_BASE_NAME,
17-
JEST_CONFIG_EXT_CJS,
22+
JEST_CONFIG_EXT_MJS,
1823
JEST_CONFIG_EXT_JS,
1924
JEST_CONFIG_EXT_ORDER,
2025
PACKAGE_JSON,
21-
} from './constants';
22-
import generateConfigFile from './generate_config_file';
23-
import modifyPackageJson from './modify_package_json';
24-
import {ProjectPackageJson} from './types';
26+
} = constants;
2527

2628
type PromptsResults = {
2729
clearMocks: boolean;
@@ -65,7 +67,7 @@ export default async (rootDir: string = realpath(process.cwd())) => {
6567
rootDir,
6668
getConfigFilename(
6769
projectPackageJson.type === 'module'
68-
? JEST_CONFIG_EXT_CJS
70+
? JEST_CONFIG_EXT_MJS
6971
: JEST_CONFIG_EXT_JS,
7072
),
7173
);
@@ -131,7 +133,11 @@ export default async (rootDir: string = realpath(process.cwd())) => {
131133
console.log(`✏️ Modified ${chalk.cyan(projectPackageJsonPath)}`);
132134
}
133135

134-
const generatedConfig = generateConfigFile(results);
136+
const generatedConfig = generateConfigFile(
137+
results,
138+
projectPackageJson.type === 'module' ||
139+
jestConfigPath.endsWith(JEST_CONFIG_EXT_MJS),
140+
);
135141

136142
fs.writeFileSync(jestConfigPath, generatedConfig);
137143

‎packages/jest-config/src/__tests__/Defaults.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
import {defaults} from '../index';
99

10+
jest.mock('../importMjs', () => (s: string) => import(s));
11+
1012
test('get configuration defaults', () => {
1113
expect(defaults).toBeDefined();
1214
});

‎packages/jest-config/src/__tests__/readConfig.test.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77

88
import {readConfig} from '../index';
99

10-
test('readConfig() throws when an object is passed without a file path', () => {
11-
expect(() => {
10+
jest.mock('../importMjs', () => (s: string) => import(s));
11+
12+
test('readConfig() throws when an object is passed without a file path', async () => {
13+
await expect(
1214
readConfig(
1315
// @ts-ignore
1416
null /* argv */,
1517
{} /* packageRootOrConfig */,
1618
false /* skipArgvConfigOption */,
1719
null /* parentConfigPath */,
18-
);
19-
}).toThrowError(
20+
),
21+
).rejects.toThrowError(
2022
'Jest: Cannot use configuration as an object without a file path',
2123
);
2224
});

‎packages/jest-config/src/__tests__/readConfigs.test.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
import {readConfigs} from '../index';
99

10-
test('readConfigs() throws when called without project paths', () => {
11-
expect(() => {
10+
jest.mock('../importMjs', () => (s: string) => import(s));
11+
12+
test('readConfigs() throws when called without project paths', async () => {
13+
await expect(
1214
// @ts-ignore
13-
readConfigs(null /* argv */, [] /* projectPaths */);
14-
}).toThrowError('jest: No configuration found for any project.');
15+
readConfigs(null /* argv */, [] /* projectPaths */),
16+
).rejects.toThrowError('jest: No configuration found for any project.');
1517
});

‎packages/jest-config/src/constants.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ export const DEFAULT_REPORTER_LABEL = 'default';
1313
export const PACKAGE_JSON = 'package.json';
1414
export const JEST_CONFIG_BASE_NAME = 'jest.config';
1515
export const JEST_CONFIG_EXT_CJS = '.cjs';
16+
export const JEST_CONFIG_EXT_MJS = '.mjs';
1617
export const JEST_CONFIG_EXT_JS = '.js';
1718
export const JEST_CONFIG_EXT_JSON = '.json';
1819
export const JEST_CONFIG_EXT_ORDER = Object.freeze([
1920
JEST_CONFIG_EXT_JS,
21+
JEST_CONFIG_EXT_MJS,
2022
JEST_CONFIG_EXT_CJS,
2123
JEST_CONFIG_EXT_JSON,
2224
]);

‎packages/jest-config/src/importMjs.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
// this is in a separate file so that node 8 don't explode with a syntax error.
9+
// Remove this file when we drop support for Node 8
10+
export default (specifier: string) => import(specifier);

‎packages/jest-config/src/index.ts

+39-34
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export {default as deprecationEntries} from './Deprecated';
2020
export {replaceRootDirInPath} from './utils';
2121
export {default as defaults} from './Defaults';
2222
export {default as descriptions} from './Descriptions';
23-
import {JEST_CONFIG_EXT_ORDER} from './constants';
23+
import * as constants from './constants';
24+
export {constants};
2425

2526
type ReadConfig = {
2627
configPath: Config.Path | null | undefined;
@@ -29,7 +30,7 @@ type ReadConfig = {
2930
projectConfig: Config.ProjectConfig;
3031
};
3132

32-
export function readConfig(
33+
export async function readConfig(
3334
argv: Config.Argv,
3435
packageRootOrConfig: Config.Path | Config.InitialOptions,
3536
// Whether it needs to look into `--config` arg passed to CLI.
@@ -39,7 +40,7 @@ export function readConfig(
3940
skipArgvConfigOption?: boolean,
4041
parentConfigPath?: Config.Path | null,
4142
projectIndex: number = Infinity,
42-
): ReadConfig {
43+
): Promise<ReadConfig> {
4344
let rawOptions;
4445
let configPath = null;
4546

@@ -74,11 +75,11 @@ export function readConfig(
7475
// or a path to directory containing `package.json` or `jest.config.js`
7576
} else if (!skipArgvConfigOption && typeof argv.config == 'string') {
7677
configPath = resolveConfigPath(argv.config, process.cwd());
77-
rawOptions = readConfigFileAndSetRootDir(configPath);
78+
rawOptions = await readConfigFileAndSetRootDir(configPath);
7879
} else {
7980
// Otherwise just try to find config in the current rootDir.
8081
configPath = resolveConfigPath(packageRootOrConfig, process.cwd());
81-
rawOptions = readConfigFileAndSetRootDir(configPath);
82+
rawOptions = await readConfigFileAndSetRootDir(configPath);
8283
}
8384

8485
const {options, hasDeprecationWarnings} = normalize(
@@ -262,22 +263,22 @@ This usually means that your ${chalk.bold(
262263
//
263264
// If no projects are specified, process.cwd() will be used as the default
264265
// (and only) project.
265-
export function readConfigs(
266+
export async function readConfigs(
266267
argv: Config.Argv,
267268
projectPaths: Array<Config.Path>,
268-
): {
269+
): Promise<{
269270
globalConfig: Config.GlobalConfig;
270271
configs: Array<Config.ProjectConfig>;
271272
hasDeprecationWarnings: boolean;
272-
} {
273+
}> {
273274
let globalConfig;
274275
let hasDeprecationWarnings;
275276
let configs: Array<Config.ProjectConfig> = [];
276277
let projects = projectPaths;
277278
let configPath: Config.Path | null | undefined;
278279

279280
if (projectPaths.length === 1) {
280-
const parsedConfig = readConfig(argv, projects[0]);
281+
const parsedConfig = await readConfig(argv, projects[0]);
281282
configPath = parsedConfig.configPath;
282283

283284
hasDeprecationWarnings = parsedConfig.hasDeprecationWarnings;
@@ -298,33 +299,37 @@ export function readConfigs(
298299
? projects[0] === realpath(process.cwd())
299300
: projects[0] === process.cwd();
300301

301-
const parsedConfigs = projects
302-
.filter(root => {
303-
// Ignore globbed files that cannot be `require`d.
304-
if (
305-
typeof root === 'string' &&
306-
fs.existsSync(root) &&
307-
!fs.lstatSync(root).isDirectory() &&
308-
!JEST_CONFIG_EXT_ORDER.some(ext => root.endsWith(ext))
309-
) {
310-
return false;
311-
}
302+
const parsedConfigs = await Promise.all(
303+
projects
304+
.filter(root => {
305+
// Ignore globbed files that cannot be `require`d.
306+
if (
307+
typeof root === 'string' &&
308+
fs.existsSync(root) &&
309+
!fs.lstatSync(root).isDirectory() &&
310+
!constants.JEST_CONFIG_EXT_ORDER.some(ext => root.endsWith(ext))
311+
) {
312+
return false;
313+
}
312314

313-
return true;
314-
})
315-
.map((root, projectIndex) => {
316-
const projectIsTheOnlyProject =
317-
projectIndex === 0 && projects.length === 1;
318-
const skipArgvConfigOption = !(projectIsTheOnlyProject && projectIsCwd);
315+
return true;
316+
})
317+
.map((root, projectIndex) => {
318+
const projectIsTheOnlyProject =
319+
projectIndex === 0 && projects.length === 1;
320+
const skipArgvConfigOption = !(
321+
projectIsTheOnlyProject && projectIsCwd
322+
);
319323

320-
return readConfig(
321-
argv,
322-
root,
323-
skipArgvConfigOption,
324-
configPath,
325-
projectIndex,
326-
);
327-
});
324+
return readConfig(
325+
argv,
326+
root,
327+
skipArgvConfigOption,
328+
configPath,
329+
projectIndex,
330+
);
331+
}),
332+
);
328333

329334
ensureNoDuplicateConfigs(parsedConfigs, projects);
330335
configs = parsedConfigs.map(({projectConfig}) => projectConfig);

‎packages/jest-config/src/readConfigFileAndSetRootDir.ts

+43-13
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,56 @@ import * as fs from 'fs';
1010
import {Config} from '@jest/types';
1111
// @ts-ignore: vendored
1212
import jsonlint from './vendor/jsonlint';
13-
import {PACKAGE_JSON} from './constants';
13+
import {
14+
JEST_CONFIG_EXT_JSON,
15+
JEST_CONFIG_EXT_MJS,
16+
PACKAGE_JSON,
17+
} from './constants';
18+
import importMjs from './importMjs';
1419

1520
// Read the configuration and set its `rootDir`
1621
// 1. If it's a `package.json` file, we look into its "jest" property
1722
// 2. For any other file, we just require it.
18-
export default (configPath: Config.Path): Config.InitialOptions => {
19-
const isJSON = configPath.endsWith('.json');
23+
export default async function readConfigFileAndSetRootDir(
24+
configPath: Config.Path,
25+
): Promise<Config.InitialOptions> {
26+
const isJSON = configPath.endsWith(JEST_CONFIG_EXT_JSON);
27+
const isMjs = configPath.endsWith(JEST_CONFIG_EXT_MJS);
Has conversations. Original line has conversations.
2028
let configObject;
2129

22-
try {
23-
configObject = require(configPath);
24-
} catch (error) {
25-
if (isJSON) {
26-
throw new Error(
27-
`Jest: Failed to parse config file ${configPath}\n` +
28-
` ${jsonlint.errors(fs.readFileSync(configPath, 'utf8'))}`,
29-
);
30-
} else {
30+
if (isMjs) {
31+
try {
32+
const importedConfig = await importMjs(configPath);
33+
34+
if (!importedConfig.default) {
35+
throw new Error(
36+
`Jest: Failed to load mjs config file ${configPath} - did you use a default export?`,
37+
);
38+
}
39+
40+
configObject = importedConfig.default;
41+
} catch (error) {
42+
if (error.message === 'Not supported') {
43+
throw new Error(
44+
`Jest: Your version of Node does not support dynamic import - please enable it or use a .cjs file extension for file ${configPath}`,
45+
);
46+
}
47+
3148
throw error;
3249
}
50+
} else {
51+
try {
52+
configObject = require(configPath);
53+
} catch (error) {
54+
if (isJSON) {
55+
throw new Error(
56+
`Jest: Failed to parse config file ${configPath}\n` +
57+
` ${jsonlint.errors(fs.readFileSync(configPath, 'utf8'))}`,
58+
);
59+
} else {
60+
throw error;
61+
}
62+
}
3363
}
3464

3565
if (configPath.endsWith(PACKAGE_JSON)) {
@@ -53,4 +83,4 @@ export default (configPath: Config.Path): Config.InitialOptions => {
5383
}
5484

5585
return configObject;
56-
};
86+
}

‎packages/jest-core/src/cli/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const runCLI = async (
4949
const outputStream =
5050
argv.json || argv.useStderr ? process.stderr : process.stdout;
5151

52-
const {globalConfig, configs, hasDeprecationWarnings} = readConfigs(
52+
const {globalConfig, configs, hasDeprecationWarnings} = await readConfigs(
5353
argv,
5454
projects,
5555
);

‎packages/jest-runtime/src/cli/index.ts

+23-23
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {VERSION} from '../version';
2020
import {Context} from '../types';
2121
import * as args from './args';
2222

23-
export function run(cliArgv?: Config.Argv, cliInfo?: Array<string>) {
23+
export async function run(cliArgv?: Config.Argv, cliInfo?: Array<string>) {
2424
const realFs = require('fs');
2525
const fs = require('graceful-fs');
2626
fs.gracefulify(realFs);
@@ -62,7 +62,7 @@ export function run(cliArgv?: Config.Argv, cliInfo?: Array<string>) {
6262
const info = cliInfo ? ', ' + cliInfo.join(', ') : '';
6363
console.log(`Using Jest Runtime v${VERSION}${info}`);
6464
}
65-
const options = readConfig(argv, root);
65+
const options = await readConfig(argv, root);
6666
const globalConfig = options.globalConfig;
6767
// Always disable automocking in scripts.
6868
const config: Config.ProjectConfig = {
@@ -73,26 +73,26 @@ export function run(cliArgv?: Config.Argv, cliInfo?: Array<string>) {
7373
// Break circular dependency
7474
const Runtime: any = require('..');
7575

76-
(Runtime.createContext(config, {
77-
maxWorkers: Math.max(cpus().length - 1, 1),
78-
watchman: globalConfig.watchman,
79-
}) as Promise<Context>)
80-
.then(hasteMap => {
81-
const Environment: typeof JestEnvironment = require(config.testEnvironment);
82-
const environment = new Environment(config);
83-
setGlobal(
84-
environment.global,
85-
'console',
86-
new CustomConsole(process.stdout, process.stderr),
87-
);
88-
setGlobal(environment.global, 'jestProjectConfig', config);
89-
setGlobal(environment.global, 'jestGlobalConfig', globalConfig);
90-
91-
const runtime = new Runtime(config, environment, hasteMap.resolver);
92-
runtime.requireModule(filePath);
93-
})
94-
.catch(e => {
95-
console.error(chalk.red(e.stack || e));
96-
process.on('exit', () => (process.exitCode = 1));
76+
try {
77+
const hasteMap: Context = await Runtime.createContext(config, {
78+
maxWorkers: Math.max(cpus().length - 1, 1),
79+
watchman: globalConfig.watchman,
9780
});
81+
82+
const Environment: typeof JestEnvironment = require(config.testEnvironment);
83+
const environment = new Environment(config);
84+
setGlobal(
85+
environment.global,
86+
'console',
87+
new CustomConsole(process.stdout, process.stderr),
88+
);
89+
setGlobal(environment.global, 'jestProjectConfig', config);
90+
setGlobal(environment.global, 'jestGlobalConfig', globalConfig);
91+
92+
const runtime = new Runtime(config, environment, hasteMap.resolver);
93+
runtime.requireModule(filePath);
94+
} catch (e) {
95+
console.error(chalk.red(e.stack || e));
96+
process.on('exit', () => (process.exitCode = 1));
97+
}
9898
}

‎scripts/build.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,14 @@ function buildFile(file, silent) {
149149
Array.isArray(plugin) &&
150150
plugin[0] === '@babel/plugin-transform-modules-commonjs'
151151
) {
152-
return [plugin[0], Object.assign({}, plugin[1], {lazy: true})];
152+
return [
153+
plugin[0],
154+
Object.assign({}, plugin[1], {
155+
lazy: string =>
156+
// we want to lazyload all non-local modules plus `importMjs` - the latter to avoid syntax errors. Set to just `true` when we drop support for node 8
157+
!string.startsWith('./') || string === './importMjs',
158+
}),
159+
];
153160
}
154161

155162
return plugin;

0 commit comments

Comments
 (0)
Please sign in to comment.