diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e78f4e509b2..f64017b68461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,9 @@ - `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346)) - `[expect]` Expose `AsymmetricMatchers` and `RawMatcherFn` interfaces ([#12363](https://github.com/facebook/jest/pull/12363)) -- `[jest-environment-jsdom]` Make `jsdom` accessible to extending environments again ([#12232](https://github.com/facebook/jest/pull/12232)) - `[jest-config]` Correctly detect CI environment and update snapshots accordingly ([#12378](https://github.com/facebook/jest/pull/12378)) +- `[jest-config]` Pass `moduleTypes` to `ts-node` to enforce CJS when transpiling ([#12397](https://github.com/facebook/jest/pull/12397)) +- `[jest-environment-jsdom]` Make `jsdom` accessible to extending environments again ([#12232](https://github.com/facebook/jest/pull/12232)) - `[jest-jasmine2, jest-types]` [**BREAKING**] Move all `jasmine` specific types from `@jest/types` to its own package ([#12125](https://github.com/facebook/jest/pull/12125)) ### Chore & Maintenance diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index fa4092ad7428..6ff86476f376 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -5,6 +5,9 @@ * LICENSE file in the root directory of this source tree. */ +import {resolve} from 'path'; +import execa = require('execa'); +import {existsSync} from 'graceful-fs'; import {onNodeVersions} from '@jest/test-utils'; import {getConfig} from '../runJest'; @@ -44,4 +47,34 @@ onNodeVersions('>=12.17.0', () => { name: 'Config from js file', }); }); + + describe('typescript', () => { + beforeAll(async () => { + // the typescript config test needs `@jest/types` to be built + const cwd = resolve(__dirname, '../../'); + const typesPackageDirectory = 'packages/jest-types'; + + const indexDTsFile = resolve( + cwd, + typesPackageDirectory, + 'build/index.d.ts', + ); + + if (!existsSync(indexDTsFile)) { + await execa('tsc', ['-b', typesPackageDirectory], {cwd}); + } + }, 60_000); + + test('reads config from ts file when package.json#type=module', () => { + const {configs} = getConfig('esm-config/ts', [], { + skipPkgJsonCheck: true, + }); + + expect(configs).toHaveLength(1); + expect(configs[0].displayName).toEqual({ + color: 'white', + name: 'Config from ts file', + }); + }); + }); }); diff --git a/e2e/esm-config/ts/__tests__/test.js b/e2e/esm-config/ts/__tests__/test.js new file mode 100644 index 000000000000..2b4a7ced6f45 --- /dev/null +++ b/e2e/esm-config/ts/__tests__/test.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +test('dummy test', () => { + expect(1).toBe(1); +}); diff --git a/e2e/esm-config/ts/jest.config.ts b/e2e/esm-config/ts/jest.config.ts new file mode 100644 index 000000000000..ec7cb04aa093 --- /dev/null +++ b/e2e/esm-config/ts/jest.config.ts @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import type {Config} from '@jest/types'; + +const config: Config.InitialOptions = { + displayName: 'Config from ts file', + testEnvironment: 'node', +}; + +export default () => config; diff --git a/e2e/esm-config/ts/package.json b/e2e/esm-config/ts/package.json new file mode 100644 index 000000000000..3dbc1ca591c0 --- /dev/null +++ b/e2e/esm-config/ts/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/e2e/runJest.ts b/e2e/runJest.ts index 3086fb7316f6..dc4f2bf0790c 100644 --- a/e2e/runJest.ts +++ b/e2e/runJest.ts @@ -266,13 +266,18 @@ export function getConfig( configs: Array; version: string; } { - const {exitCode, stdout} = runJest( + const {exitCode, stdout, stderr} = runJest( dir, args.concat('--show-config'), options, ); - expect(exitCode).toBe(0); + try { + expect(exitCode).toBe(0); + } catch (error) { + console.error('Exit code is not 0', {stderr, stdout}); + throw error; + } return JSON.parse(stdout); } diff --git a/packages/jest-config/src/readConfigFileAndSetRootDir.ts b/packages/jest-config/src/readConfigFileAndSetRootDir.ts index a3e9d89abb58..000bed86e804 100644 --- a/packages/jest-config/src/readConfigFileAndSetRootDir.ts +++ b/packages/jest-config/src/readConfigFileAndSetRootDir.ts @@ -84,21 +84,7 @@ const loadTSConfigFile = async ( configPath: Config.Path, ): Promise => { // Register TypeScript compiler instance - try { - registerer ||= require('ts-node').register({ - compilerOptions: { - module: 'CommonJS', - }, - }); - } catch (e: any) { - if (e.code === 'MODULE_NOT_FOUND') { - throw new Error( - `Jest: 'ts-node' is required for the TypeScript configuration files. Make sure it is installed\nError: ${e.message}`, - ); - } - - throw e; - } + await registerTsNode(); registerer.enabled(true); @@ -113,3 +99,30 @@ const loadTSConfigFile = async ( return configObject; }; + +async function registerTsNode(): Promise { + if (registerer) { + return registerer; + } + + try { + const tsNode = await import('ts-node'); + registerer = tsNode.register({ + compilerOptions: { + module: 'CommonJS', + }, + moduleTypes: { + '**': 'cjs', + }, + }); + return registerer; + } catch (e: any) { + if (e.code === 'ERR_MODULE_NOT_FOUND') { + throw new Error( + `Jest: 'ts-node' is required for the TypeScript configuration files. Make sure it is installed\nError: ${e.message}`, + ); + } + + throw e; + } +}