diff --git a/docs/Configuration.md b/docs/Configuration.md index ad7c3d76d79f..09ef73b2437b 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -425,7 +425,15 @@ Activates notifications for test results. Default: `undefined` A preset that is used as a base for Jest's configuration. A preset should point -to an npm module that exports a `jest-preset.json` module on its top level. +to an npm module that exports a `jest-preset.json` or `jest-preset.js` module at its top level. + +Presets may also be relative filesystem paths. + +```json +{ + "preset": "./node_modules/foo-bar/jest-preset.js" +} +``` ### `projects` [array] diff --git a/packages/jest-config/src/__tests__/normalize.test.js b/packages/jest-config/src/__tests__/normalize.test.js index 19cbf8d62eb9..3145a8f16a12 100644 --- a/packages/jest-config/src/__tests__/normalize.test.js +++ b/packages/jest-config/src/__tests__/normalize.test.js @@ -859,6 +859,24 @@ describe('preset', () => { }), {virtual: true}, ); + jest.mock( + '/node_modules/with-json-ext/jest-preset.json', + () => ({ + moduleNameMapper: { + json: true, + }, + }), + {virtual: true}, + ); + jest.mock( + '/node_modules/with-js-ext/jest-preset.js', + () => ({ + moduleNameMapper: { + js: true, + }, + }), + {virtual: true}, + ); }); afterEach(() => { @@ -905,6 +923,30 @@ describe('preset', () => { }).not.toThrow(); }); + test('supports .json preset files', () => { + const {options} = normalize( + { + preset: 'with-json-ext', + rootDir: '/root/path/foo', + }, + {}, + ); + + expect(options.moduleNameMapper).toEqual([['json', true]]); + }); + + test('supports .js preset files', () => { + const {options} = normalize( + { + preset: 'with-js-ext', + rootDir: '/root/path/foo', + }, + {}, + ); + + expect(options.moduleNameMapper).toEqual([['js', true]]); + }); + test('merges with options', () => { const {options} = normalize( { diff --git a/packages/jest-config/src/normalize.js b/packages/jest-config/src/normalize.js index e7fba4434f83..5e475fcfe03a 100644 --- a/packages/jest-config/src/normalize.js +++ b/packages/jest-config/src/normalize.js @@ -39,8 +39,8 @@ import DEPRECATED_CONFIG from './deprecated'; import setFromArgv from './set_from_argv'; import VALID_CONFIG from './valid_config'; const ERROR = `${BULLET}Validation Error`; -const JSON_EXTENSION = '.json'; -const PRESET_NAME = 'jest-preset' + JSON_EXTENSION; +const PRESET_EXTENSIONS = ['.json', '.js']; +const PRESET_NAME = 'jest-preset'; const createConfigError = message => new ValidationError(ERROR, message, DOCUMENTATION_NOTE); @@ -52,14 +52,35 @@ const setupPreset = ( let preset; const presetPath = _replaceRootDirInPath(options.rootDir, optionsPreset); const presetModule = Resolver.findNodeModule( - presetPath.endsWith(JSON_EXTENSION) + presetPath.charAt(0) === '.' ? presetPath : path.join(presetPath, PRESET_NAME), { basedir: options.rootDir, + extensions: PRESET_EXTENSIONS, }, ); + // const foundModule = PRESET_EXTENSIONS.some(ext => { + // const presetModule = Resolver.findNodeModule( + // presetPath.charAt(0) === '.' || presetPath.endsWith(ext) + // ? presetPath + // : path.join(presetPath, PRESET_NAME + ext), + // { + // basedir: options.rootDir, + // }, + // ); + // + // try { + // // $FlowFixMe + // preset = (require(presetModule): InitialOptions); + // } catch (error) { + // return false; + // } + // + // return true; + // }); + try { // $FlowFixMe preset = (require(presetModule): InitialOptions);