From 8294bab1ebbf9bac7d2aa01abd256bbca4952eb7 Mon Sep 17 00:00:00 2001 From: hisco <39222286+hisco@users.noreply.github.com> Date: Sat, 9 May 2020 12:10:12 +0300 Subject: [PATCH] feat: support config files exporting (`async`) `function`s (#10001) --- CHANGELOG.md | 2 + docs/Configuration.md | 8 ++++ .../src/__tests__/readConfigs.test.ts | 40 ++++++++++++++++++- packages/jest-config/src/index.ts | 8 +++- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59609112b0a5..cca2602e30cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-config]` Support config files exporting (`async`) `function`s ([#10001](https://github.com/facebook/jest/pull/10001)) + ### Fixes - `[jest-jasmine2]` Stop adding `:` after an error that has no message ([#9990](https://github.com/facebook/jest/pull/9990)) diff --git a/docs/Configuration.md b/docs/Configuration.md index b429dc017d68..2020673b064b 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -18,9 +18,17 @@ Or through JavaScript: ```js // jest.config.js +//Sync object module.exports = { verbose: true, }; + +//Or async function +module.exports = async () => { + return { + verbose: true, + }; +}; ``` Please keep in mind that the resulting configuration must be JSON-serializable. diff --git a/packages/jest-config/src/__tests__/readConfigs.test.ts b/packages/jest-config/src/__tests__/readConfigs.test.ts index be939256c090..97fa1b351bf9 100644 --- a/packages/jest-config/src/__tests__/readConfigs.test.ts +++ b/packages/jest-config/src/__tests__/readConfigs.test.ts @@ -4,12 +4,50 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ - +import {Config} from '@jest/types'; import {readConfigs} from '../index'; +let mockResult; +jest.mock('graceful-fs', () => ({ + ...jest.requireActual('fs'), + existsSync: jest.fn(() => true), + lstatSync: jest.fn(() => ({ + isDirectory: () => false, + })), +})); +jest.mock('../readConfigFileAndSetRootDir', () => jest.fn(() => mockResult)); + test('readConfigs() throws when called without project paths', async () => { await expect( // @ts-ignore readConfigs(null /* argv */, [] /* projectPaths */), ).rejects.toThrowError('jest: No configuration found for any project.'); }); + +test('readConfigs() loads async config file', async () => { + mockResult = jest.fn(async () => ({ + rootDir: './', + })); + await expect( + // @ts-ignore + readConfigs( + {} /* argv */, + ['./some-jest-config-file.js'] /* projectPaths */, + ), + ).resolves.toHaveProperty('configs'); + expect(mockResult).toHaveBeenCalled(); +}); + +test('readConfigs() reject if async was rejected', async () => { + mockResult = jest.fn(async () => { + throw new Error('Some error'); + }); + await expect( + // @ts-ignore + readConfigs( + {} /* argv */, + ['./some-jest-config-file.js'] /* projectPaths */, + ), + ).rejects.toBeTruthy(); + expect(mockResult).toHaveBeenCalled(); +}); diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 68d6b5ddf55c..de88d4423cf8 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -41,7 +41,9 @@ export async function readConfig( parentConfigPath?: Config.Path | null, projectIndex: number = Infinity, ): Promise { - let rawOptions; + let rawOptions: + | Config.InitialOptions + | (() => Config.InitialOptions | Promise); let configPath = null; if (typeof packageRootOrConfig !== 'string') { @@ -82,6 +84,10 @@ export async function readConfig( rawOptions = await readConfigFileAndSetRootDir(configPath); } + if (typeof rawOptions === 'function') { + rawOptions = await rawOptions(); + } + const {options, hasDeprecationWarnings} = normalize( rawOptions, argv,