From 359873b47f0a5ec0e7ec6079a62f800296d7387e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:14:47 +0100 Subject: [PATCH 01/10] chore: add integration test for TS config and Node ESM mode --- e2e/__tests__/esmConfigFile.test.ts | 12 ++++++++++++ e2e/esm-config/ts/__tests__/test.js | 10 ++++++++++ e2e/esm-config/ts/jest.config.ts | 15 +++++++++++++++ e2e/esm-config/ts/package.json | 3 +++ e2e/esm-config/ts/tsconfig.json | 8 ++++++++ 5 files changed, 48 insertions(+) create mode 100644 e2e/esm-config/ts/__tests__/test.js create mode 100644 e2e/esm-config/ts/jest.config.ts create mode 100644 e2e/esm-config/ts/package.json create mode 100644 e2e/esm-config/ts/tsconfig.json diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index fa4092ad7428..690d7e509f19 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -44,4 +44,16 @@ onNodeVersions('>=12.17.0', () => { name: 'Config from js file', }); }); + + 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/esm-config/ts/tsconfig.json b/e2e/esm-config/ts/tsconfig.json new file mode 100644 index 000000000000..171e02d57236 --- /dev/null +++ b/e2e/esm-config/ts/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.json", + "ts-node": { + "moduleTypes": { + "jest.config.ts": "cjs" + } + } +} From 67bce365c3e60d04acad455fee0cf29a6c03b001 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:30:40 +0100 Subject: [PATCH 02/10] log stdout and stderrr --- e2e/runJest.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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); } From dfad343bb4e6b2807abba373669cd605cffada6e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:36:55 +0100 Subject: [PATCH 03/10] override in config, not separate file --- e2e/esm-config/ts/tsconfig.json | 8 -------- packages/jest-config/src/readConfigFileAndSetRootDir.ts | 3 +++ 2 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 e2e/esm-config/ts/tsconfig.json diff --git a/e2e/esm-config/ts/tsconfig.json b/e2e/esm-config/ts/tsconfig.json deleted file mode 100644 index 171e02d57236..000000000000 --- a/e2e/esm-config/ts/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "ts-node": { - "moduleTypes": { - "jest.config.ts": "cjs" - } - } -} diff --git a/packages/jest-config/src/readConfigFileAndSetRootDir.ts b/packages/jest-config/src/readConfigFileAndSetRootDir.ts index a3e9d89abb58..47bbefec1715 100644 --- a/packages/jest-config/src/readConfigFileAndSetRootDir.ts +++ b/packages/jest-config/src/readConfigFileAndSetRootDir.ts @@ -89,6 +89,9 @@ const loadTSConfigFile = async ( compilerOptions: { module: 'CommonJS', }, + moduleTypes: { + '**': 'cjs', + }, }); } catch (e: any) { if (e.code === 'MODULE_NOT_FOUND') { From 8a880b0dc4af868983a386fa755b46ac51ac0140 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:39:04 +0100 Subject: [PATCH 04/10] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 From f5dc8217b8b25ab7bef6d8b6bab5958afdae0f7f Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:47:56 +0100 Subject: [PATCH 05/10] make sure @jest/types exist --- e2e/__tests__/esmConfigFile.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index 690d7e509f19..669bc8845a4b 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +import {resolve} from 'path'; +import execa = require('execa'); import {onNodeVersions} from '@jest/test-utils'; import {getConfig} from '../runJest'; @@ -20,6 +22,12 @@ test('reads config from cjs file', () => { }); }); +beforeAll(async () => { + await execa('tsc', ['-b', 'packages/jest-types'], { + cwd: resolve(__dirname, '../../'), + }); +}, 30_000); + onNodeVersions('>=12.17.0', () => { test('reads config from mjs file', () => { const {configs} = getConfig('esm-config/mjs', [], { From bd1da78eb427e099105e6472f467cb4493a4ae69 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:49:40 +0100 Subject: [PATCH 06/10] move --- e2e/__tests__/esmConfigFile.test.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index 669bc8845a4b..e16612eb2612 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -10,6 +10,13 @@ import execa = require('execa'); import {onNodeVersions} from '@jest/test-utils'; import {getConfig} from '../runJest'; +beforeAll(async () => { + // the typescript config test needs this type to exist + await execa('tsc', ['-b', 'packages/jest-types'], { + cwd: resolve(__dirname, '../../'), + }); +}, 30_000); + test('reads config from cjs file', () => { const {configs} = getConfig('esm-config/cjs', [], { skipPkgJsonCheck: true, @@ -22,12 +29,6 @@ test('reads config from cjs file', () => { }); }); -beforeAll(async () => { - await execa('tsc', ['-b', 'packages/jest-types'], { - cwd: resolve(__dirname, '../../'), - }); -}, 30_000); - onNodeVersions('>=12.17.0', () => { test('reads config from mjs file', () => { const {configs} = getConfig('esm-config/mjs', [], { From 1479bbb033b2f1307a340cd678e1af4478b092c5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 17:57:45 +0100 Subject: [PATCH 07/10] chore: load ts-node using `import`, not `require` --- .../src/readConfigFileAndSetRootDir.ts | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/jest-config/src/readConfigFileAndSetRootDir.ts b/packages/jest-config/src/readConfigFileAndSetRootDir.ts index 47bbefec1715..000bed86e804 100644 --- a/packages/jest-config/src/readConfigFileAndSetRootDir.ts +++ b/packages/jest-config/src/readConfigFileAndSetRootDir.ts @@ -84,8 +84,30 @@ const loadTSConfigFile = async ( configPath: Config.Path, ): Promise => { // Register TypeScript compiler instance + await registerTsNode(); + + registerer.enabled(true); + + let configObject = interopRequireDefault(require(configPath)).default; + + // In case the config is a function which imports more Typescript code + if (typeof configObject === 'function') { + configObject = await configObject(); + } + + registerer.enabled(false); + + return configObject; +}; + +async function registerTsNode(): Promise { + if (registerer) { + return registerer; + } + try { - registerer ||= require('ts-node').register({ + const tsNode = await import('ts-node'); + registerer = tsNode.register({ compilerOptions: { module: 'CommonJS', }, @@ -93,8 +115,9 @@ const loadTSConfigFile = async ( '**': 'cjs', }, }); + return registerer; } catch (e: any) { - if (e.code === 'MODULE_NOT_FOUND') { + 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}`, ); @@ -102,17 +125,4 @@ const loadTSConfigFile = async ( throw e; } - - registerer.enabled(true); - - let configObject = interopRequireDefault(require(configPath)).default; - - // In case the config is a function which imports more Typescript code - if (typeof configObject === 'function') { - configObject = await configObject(); - } - - registerer.enabled(false); - - return configObject; -}; +} From fa260d3af7a8a75fdb400d96455c2142277049d6 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 18:17:00 +0100 Subject: [PATCH 08/10] increase timeout --- e2e/__tests__/esmConfigFile.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index e16612eb2612..69a81dc7bcf7 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -15,7 +15,7 @@ beforeAll(async () => { await execa('tsc', ['-b', 'packages/jest-types'], { cwd: resolve(__dirname, '../../'), }); -}, 30_000); +}, 60_000); test('reads config from cjs file', () => { const {configs} = getConfig('esm-config/cjs', [], { From 48bb8ae520fa81c7652291eff617e79c83d9347b Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 18:20:57 +0100 Subject: [PATCH 09/10] skip tsc run if file already exists --- e2e/__tests__/esmConfigFile.test.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index 69a81dc7bcf7..3a2e72fce0a2 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -7,14 +7,20 @@ import {resolve} from 'path'; import execa = require('execa'); +import {existsSync} from 'graceful-fs'; import {onNodeVersions} from '@jest/test-utils'; import {getConfig} from '../runJest'; beforeAll(async () => { - // the typescript config test needs this type to exist - await execa('tsc', ['-b', 'packages/jest-types'], { - cwd: resolve(__dirname, '../../'), - }); + // 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 cjs file', () => { From 43f685eb6b533aab3095774f46ec0452e2469ecf Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 15 Feb 2022 18:22:34 +0100 Subject: [PATCH 10/10] group ts test inside where it belongs --- e2e/__tests__/esmConfigFile.test.ts | 46 ++++++++++++++++------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/e2e/__tests__/esmConfigFile.test.ts b/e2e/__tests__/esmConfigFile.test.ts index 3a2e72fce0a2..6ff86476f376 100644 --- a/e2e/__tests__/esmConfigFile.test.ts +++ b/e2e/__tests__/esmConfigFile.test.ts @@ -11,18 +11,6 @@ import {existsSync} from 'graceful-fs'; import {onNodeVersions} from '@jest/test-utils'; import {getConfig} from '../runJest'; -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 cjs file', () => { const {configs} = getConfig('esm-config/cjs', [], { skipPkgJsonCheck: true, @@ -60,15 +48,33 @@ onNodeVersions('>=12.17.0', () => { }); }); - test('reads config from ts file when package.json#type=module', () => { - const {configs} = getConfig('esm-config/ts', [], { - skipPkgJsonCheck: true, - }); + describe('typescript', () => { + beforeAll(async () => { + // the typescript config test needs `@jest/types` to be built + const cwd = resolve(__dirname, '../../'); + const typesPackageDirectory = 'packages/jest-types'; - expect(configs).toHaveLength(1); - expect(configs[0].displayName).toEqual({ - color: 'white', - name: 'Config from ts file', + 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', + }); }); }); });