From f5c0d8f976c7814fd6bbbd1a35e397427ac59ed4 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Sun, 10 May 2020 13:06:50 +0200 Subject: [PATCH] Move jest-runtime CLI into jest-repl Fixes #10011 --- CHANGELOG.md | 1 + jest.config.js | 1 + .../src/__tests__/SearchSource.test.ts | 2 - .../bin/jest-runtime-cli.js} | 2 +- packages/jest-repl/package.json | 7 +- .../src/__tests__/runtime_cli.test.js | 49 +++++++++++++ .../src/__tests__/test_root/logging.js | 4 +- .../src/__tests__/test_root/throwing.js | 10 +++ packages/jest-repl/src/cli/args.ts | 37 +++++++++- packages/jest-repl/src/cli/index.ts | 6 +- .../src/cli/runtime-cli.ts} | 5 +- .../src => jest-repl/src/cli}/version.ts | 2 +- packages/jest-repl/tsconfig.json | 6 +- packages/jest-runtime/package.json | 1 - .../src/__mocks__/createRuntime.js | 73 +++++++++++++++++-- .../src/__tests__/runtime_cli.test.js | 51 ------------- packages/jest-runtime/src/cli/args.ts | 44 ----------- packages/jest-runtime/src/index.ts | 10 +-- packages/jest-runtime/tsconfig.json | 1 - yarn.lock | 6 +- 20 files changed, 194 insertions(+), 124 deletions(-) rename packages/{jest-runtime/bin/jest-runtime.js => jest-repl/bin/jest-runtime-cli.js} (87%) create mode 100644 packages/jest-repl/src/__tests__/runtime_cli.test.js rename packages/{jest-runtime => jest-repl}/src/__tests__/test_root/logging.js (78%) create mode 100644 packages/jest-repl/src/__tests__/test_root/throwing.js rename packages/{jest-runtime/src/cli/index.ts => jest-repl/src/cli/runtime-cli.ts} (97%) rename packages/{jest-runtime/src => jest-repl/src/cli}/version.ts (80%) delete mode 100644 packages/jest-runtime/src/__tests__/runtime_cli.test.js delete mode 100644 packages/jest-runtime/src/cli/args.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 25f7b3a3b2e5..40e13a7d6c55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - `[*]` [**BREAKING**] Add `exports` field to all `package.json`s ([#9921](https://github.com/facebook/jest/pull/9921)) - `[jest-config]` [**BREAKING**] Remove `enabledTestsMap` config, use `filter` instead ([#10787](https://github.com/facebook/jest/pull/10787)) - `[jest-resolve]` [**BREAKING**] Migrate to ESM ([#10688](https://github.com/facebook/jest/pull/10688)) +- `[jest-repl, jest-runtime]` [**BREAKING**] Move the `jest-runtime` CLI into `jest-repl` ([#10016](https://github.com/facebook/jest/pull/10016)) ### Performance diff --git a/jest.config.js b/jest.config.js index d6d551dd506d..1aeed82b2d47 100644 --- a/jest.config.js +++ b/jest.config.js @@ -50,6 +50,7 @@ module.exports = { '/packages/jest-haste-map/src/__tests__/haste_impl.js', '/packages/jest-haste-map/src/__tests__/dependencyExtractor.js', '/packages/jest-haste-map/src/__tests__/test_dotfiles_root/', + '/packages/jest-repl/src/__tests__/test_root', '/packages/jest-resolve-dependencies/src/__tests__/__fixtures__/', '/packages/jest-runtime/src/__tests__/defaultResolver.js', '/packages/jest-runtime/src/__tests__/module_dir/', diff --git a/packages/jest-core/src/__tests__/SearchSource.test.ts b/packages/jest-core/src/__tests__/SearchSource.test.ts index 86c0d73b32b4..21cfcd1c3b6a 100644 --- a/packages/jest-core/src/__tests__/SearchSource.test.ts +++ b/packages/jest-core/src/__tests__/SearchSource.test.ts @@ -451,14 +451,12 @@ describe('SearchSource', () => { it('finds tests that depend directly on the path', () => { const filePath = path.join(rootDir, 'RegularModule.js'); const file2Path = path.join(rootDir, 'RequireRegularModule.js'); - const loggingDep = path.join(rootDir, 'logging.js'); const parentDep = path.join(rootDir, 'ModuleWithSideEffects.js'); const data = searchSource.findRelatedTests(new Set([filePath]), false); expect(toPaths(data.tests).sort()).toEqual([ parentDep, filePath, file2Path, - loggingDep, rootPath, ]); }); diff --git a/packages/jest-runtime/bin/jest-runtime.js b/packages/jest-repl/bin/jest-runtime-cli.js similarity index 87% rename from packages/jest-runtime/bin/jest-runtime.js rename to packages/jest-repl/bin/jest-runtime-cli.js index 6a510e724c5f..c54353904cd7 100755 --- a/packages/jest-runtime/bin/jest-runtime.js +++ b/packages/jest-repl/bin/jest-runtime-cli.js @@ -10,4 +10,4 @@ if (process.env.NODE_ENV == null) { process.env.NODE_ENV = 'test'; } -require('../build/cli').run(); +require('../build/cli/runtime-cli').run(); diff --git a/packages/jest-repl/package.json b/packages/jest-repl/package.json index 909c04faba35..5c56c2d8ee2e 100644 --- a/packages/jest-repl/package.json +++ b/packages/jest-repl/package.json @@ -15,17 +15,22 @@ "./bin/jest-repl": "./bin/jest-repl.js" }, "dependencies": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", "@jest/transform": "^26.6.2", "@jest/types": "^26.6.2", + "chalk": "^4.0.0", "jest-config": "^26.6.3", "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", "jest-validate": "^26.6.2", "repl": "^0.1.3", "yargs": "^16.0.3" }, "devDependencies": { "@jest/test-utils": "^26.6.2", - "@types/yargs": "^15.0.0" + "@types/yargs": "^15.0.0", + "execa": "^4.0.0" }, "bin": "./bin/jest-repl.js", "engines": { diff --git a/packages/jest-repl/src/__tests__/runtime_cli.test.js b/packages/jest-repl/src/__tests__/runtime_cli.test.js new file mode 100644 index 000000000000..90f17224d3f4 --- /dev/null +++ b/packages/jest-repl/src/__tests__/runtime_cli.test.js @@ -0,0 +1,49 @@ +/** + * 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 path from 'path'; +import {sync as spawnSync} from 'execa'; + +const JEST_RUNTIME = path.resolve(__dirname, '../../bin/jest-runtime-cli.js'); + +const run = args => + spawnSync(JEST_RUNTIME, args, { + cwd: process.cwd(), + env: process.env, + reject: false, + }); + +describe('Runtime CLI', () => { + it('fails with no path', () => { + const expectedOutput = + 'Please provide a path to a script. (See --help for details)'; + expect(run([]).stdout).toBe(expectedOutput); + }); + + it('displays script output', () => { + const scriptPath = path.resolve(__dirname, './test_root/logging.js'); + expect(run([scriptPath, '--no-cache']).stdout).toMatch('Hello, world!'); + }); + + it('always disables automocking', () => { + const scriptPath = path.resolve(__dirname, './test_root/logging.js'); + const output = run([ + scriptPath, + '--no-cache', + '--config=' + + JSON.stringify({ + automock: true, + }), + ]); + expect(output.stdout).toMatch('Hello, world!'); + }); + + it('throws script errors', () => { + const scriptPath = path.resolve(__dirname, './test_root/throwing.js'); + expect(run([scriptPath, '--no-cache']).stderr).toMatch('Error: throwing'); + }); +}); diff --git a/packages/jest-runtime/src/__tests__/test_root/logging.js b/packages/jest-repl/src/__tests__/test_root/logging.js similarity index 78% rename from packages/jest-runtime/src/__tests__/test_root/logging.js rename to packages/jest-repl/src/__tests__/test_root/logging.js index 27fc7d13343f..c68f46394840 100644 --- a/packages/jest-runtime/src/__tests__/test_root/logging.js +++ b/packages/jest-repl/src/__tests__/test_root/logging.js @@ -7,7 +7,9 @@ 'use strict'; -if (require('./RegularModule').getModuleStateValue()) { +if ( + require('jest-runtime/src/__tests__/test_root/RegularModule').getModuleStateValue() +) { console.log('Hello, world!'); } else { console.log('Automocking is not properly disabled in jest-runtime.'); diff --git a/packages/jest-repl/src/__tests__/test_root/throwing.js b/packages/jest-repl/src/__tests__/test_root/throwing.js new file mode 100644 index 000000000000..9b40a996eab0 --- /dev/null +++ b/packages/jest-repl/src/__tests__/test_root/throwing.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. + */ + +'use strict'; + +throw new Error('throwing'); diff --git a/packages/jest-repl/src/cli/args.ts b/packages/jest-repl/src/cli/args.ts index 43dc5793f1f9..09f1b6392660 100644 --- a/packages/jest-repl/src/cli/args.ts +++ b/packages/jest-repl/src/cli/args.ts @@ -7,12 +7,45 @@ */ import type {Options} from 'yargs'; -import Runtime from 'jest-runtime'; export const usage = 'Usage: $0 [--config=]'; +const runtimeCLIOptions: Record< + 'cache' | 'config' | 'debug' | 'version' | 'watchman', + Options +> = { + cache: { + default: true, + description: + 'Whether to use the preprocessor cache. Disable ' + + 'the cache using --no-cache.', + type: 'boolean', + }, + config: { + alias: 'c', + description: 'The path to a Jest config file.', + type: 'string', + }, + debug: { + description: 'Print debugging info about your jest config.', + type: 'boolean', + }, + version: { + alias: 'v', + description: 'Print the version and exit', + type: 'boolean', + }, + watchman: { + default: true, + description: + 'Whether to use watchman for file crawling. Disable using ' + + '--no-watchman.', + type: 'boolean', + }, +}; + export const options: Record = { - ...Runtime.getCLIOptions(), + ...runtimeCLIOptions, replname: { alias: 'r', description: diff --git a/packages/jest-repl/src/cli/index.ts b/packages/jest-repl/src/cli/index.ts index 58a8f2db1482..339ac65a3287 100644 --- a/packages/jest-repl/src/cli/index.ts +++ b/packages/jest-repl/src/cli/index.ts @@ -10,10 +10,10 @@ import yargs = require('yargs'); import type {Config} from '@jest/types'; import {deprecationEntries} from 'jest-config'; -import Runtime from 'jest-runtime'; import {validateCLIOptions} from 'jest-validate'; import * as args from './args'; -const {version: VERSION} = require('../../package.json'); +import {run as runtimeCLI} from './runtime-cli'; +import {VERSION} from './version'; const REPL_SCRIPT = require.resolve('./repl.js'); @@ -24,5 +24,5 @@ export = function (): void { argv._ = [REPL_SCRIPT]; - Runtime.runCLI(argv, [`Jest REPL v${VERSION}`]); + runtimeCLI(argv, [`Jest REPL v${VERSION}`]); }; diff --git a/packages/jest-runtime/src/cli/index.ts b/packages/jest-repl/src/cli/runtime-cli.ts similarity index 97% rename from packages/jest-runtime/src/cli/index.ts rename to packages/jest-repl/src/cli/runtime-cli.ts index 3add89691abc..29ee1bdbef7e 100644 --- a/packages/jest-runtime/src/cli/index.ts +++ b/packages/jest-repl/src/cli/runtime-cli.ts @@ -13,10 +13,11 @@ import {CustomConsole} from '@jest/console'; import type {JestEnvironment} from '@jest/environment'; import type {Config} from '@jest/types'; import {deprecationEntries, readConfig} from 'jest-config'; +import Runtime from 'jest-runtime'; import {setGlobal, tryRealpath} from 'jest-util'; import {validateCLIOptions} from 'jest-validate'; -import {VERSION} from '../version'; import * as args from './args'; +import {VERSION} from './version'; export async function run( cliArgv?: Config.Argv, @@ -66,8 +67,6 @@ export async function run( automock: false, }; - const {default: Runtime} = await import('..'); - try { const hasteMap = await Runtime.createContext(config, { maxWorkers: Math.max(cpus().length - 1, 1), diff --git a/packages/jest-runtime/src/version.ts b/packages/jest-repl/src/cli/version.ts similarity index 80% rename from packages/jest-runtime/src/version.ts rename to packages/jest-repl/src/cli/version.ts index 6c68483e5054..589132f9db10 100644 --- a/packages/jest-runtime/src/version.ts +++ b/packages/jest-repl/src/cli/version.ts @@ -6,4 +6,4 @@ */ // For some reason, doing `require`ing here works, while inside `cli` fails -export const VERSION: string = require('../package.json').version; +export const VERSION: string = require('../../package.json').version; diff --git a/packages/jest-repl/tsconfig.json b/packages/jest-repl/tsconfig.json index 49565cc45a7e..635574018add 100644 --- a/packages/jest-repl/tsconfig.json +++ b/packages/jest-repl/tsconfig.json @@ -6,9 +6,13 @@ }, "references": [ {"path": "../jest-config"}, + {"path": "../jest-console"}, + {"path": "../jest-environment"}, {"path": "../jest-runtime"}, {"path": "../jest-transform"}, {"path": "../jest-types"}, - {"path": "../jest-validate"} + {"path": "../jest-util"}, + {"path": "../jest-validate"}, + {"path": "../test-utils"} ] } diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index 3c585ffd1a0f..991ba381fae9 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -30,7 +30,6 @@ "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-config": "^26.6.3", "jest-haste-map": "^26.6.2", "jest-message-util": "^26.6.2", "jest-mock": "^26.6.2", diff --git a/packages/jest-runtime/src/__mocks__/createRuntime.js b/packages/jest-runtime/src/__mocks__/createRuntime.js index c2d832e063d3..478359de5c2c 100644 --- a/packages/jest-runtime/src/__mocks__/createRuntime.js +++ b/packages/jest-runtime/src/__mocks__/createRuntime.js @@ -5,16 +5,72 @@ * LICENSE file in the root directory of this source tree. */ +import {tmpdir} from 'os'; import path from 'path'; +import {makeProjectConfig} from '@jest/test-utils'; +import {tryRealpath} from 'jest-util'; + +// Copy from jest-config (since we don't want to depend on this package) +const getCacheDirectory = () => { + const {getuid} = process; + const tmpdirPath = path.join(tryRealpath(tmpdir()), 'jest'); + if (getuid == null) { + return tmpdirPath; + } else { + // On some platforms tmpdir() is `/tmp`, causing conflicts between different + // users and permission issues. Adding an additional subdivision by UID can + // help. + return `${tmpdirPath}_${getuid.call(process).toString(36)}`; + } +}; + +const setupModuleNameMapper = (config, rootDir) => { + if (config && config.moduleNameMapper) { + return Object.keys(config.moduleNameMapper).map(regex => { + const item = config.moduleNameMapper && config.moduleNameMapper[regex]; + return item && [regex, item.replace('', rootDir)]; + }); + } + return []; +}; + +const setupTransform = (config, rootDir) => { + if (config && config.transform) { + const transform = config.transform; + return Object.keys(transform).map(regex => [ + regex, + path.resolve(rootDir, transform[regex]), + ]); + } + return [ + [ + '^.+\\.[jt]sx?$', + path.resolve( + __dirname, + '..', + '..', + '..', + 'babel-jest', + 'build', + 'index.js', + ), + ], + ]; +}; module.exports = async function createRuntime(filename, config) { const {default: NodeEnvironment} = await import('jest-environment-node'); const {default: Runtime} = await import('../'); - const {normalize} = await import('jest-config'); + const rootDir = path.resolve(path.dirname(filename), 'test_root'); - config = normalize( + const moduleNameMapper = setupModuleNameMapper(config, rootDir); + const transform = setupTransform(config, rootDir); + + config = makeProjectConfig( { + cacheDirectory: getCacheDirectory(), + cwd: path.resolve(__dirname, '..', '..', '..', '..'), haste: { hasteImplModulePath: path.resolve( __dirname, @@ -27,13 +83,20 @@ module.exports = async function createRuntime(filename, config) { 'haste_impl.js', ), }, + moduleDirectories: ['node_modules'], + moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'], name: 'Runtime-' + filename.replace(/\W/, '-') + '.tests', - rootDir: path.resolve(path.dirname(filename), 'test_root'), + rootDir, ...config, + moduleNameMapper, + transform, }, - {}, - ).options; + ); + + if (!config.roots.length) { + config.roots = [config.rootDir]; + } const environment = new NodeEnvironment(config); environment.global.console = console; diff --git a/packages/jest-runtime/src/__tests__/runtime_cli.test.js b/packages/jest-runtime/src/__tests__/runtime_cli.test.js deleted file mode 100644 index e0de95450d1d..000000000000 --- a/packages/jest-runtime/src/__tests__/runtime_cli.test.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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 path from 'path'; -import {sync as spawnSync} from 'execa'; - -const JEST_RUNTIME = path.resolve(__dirname, '../../bin/jest-runtime.js'); - -const run = args => - spawnSync(JEST_RUNTIME, args, { - cwd: process.cwd(), - env: process.env, - reject: false, - }); - -describe('Runtime', () => { - describe('cli', () => { - it('fails with no path', () => { - const expectedOutput = - 'Please provide a path to a script. (See --help for details)'; - expect(run([]).stdout).toBe(expectedOutput); - }); - - it('displays script output', () => { - const scriptPath = path.resolve(__dirname, './test_root/logging.js'); - expect(run([scriptPath, '--no-cache']).stdout).toMatch('Hello, world!'); - }); - - it('always disables automocking', () => { - const scriptPath = path.resolve(__dirname, './test_root/logging.js'); - const output = run([ - scriptPath, - '--no-cache', - '--config=' + - JSON.stringify({ - automock: true, - }), - ]); - expect(output.stdout).toMatch('Hello, world!'); - }); - - it('throws script errors', () => { - const scriptPath = path.resolve(__dirname, './test_root/throwing.js'); - expect(run([scriptPath, '--no-cache']).stderr).toMatch('Error: throwing'); - }); - }); -}); diff --git a/packages/jest-runtime/src/cli/args.ts b/packages/jest-runtime/src/cli/args.ts deleted file mode 100644 index 34fa4144a640..000000000000 --- a/packages/jest-runtime/src/cli/args.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 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 {Options} from 'yargs'; - -export const usage = 'Usage: $0 [--config=] '; - -export const options: Record< - 'cache' | 'config' | 'debug' | 'version' | 'watchman', - Options -> = { - cache: { - default: true, - description: - 'Whether to use the preprocessor cache. Disable ' + - 'the cache using --no-cache.', - type: 'boolean', - }, - config: { - alias: 'c', - description: 'The path to a Jest config file.', - type: 'string', - }, - debug: { - description: 'Print debugging info about your jest config.', - type: 'boolean', - }, - version: { - alias: 'v', - description: 'Print the version and exit', - type: 'boolean', - }, - watchman: { - default: true, - description: - 'Whether to use watchman for file crawling. Disable using ' + - '--no-watchman.', - type: 'boolean', - }, -}; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 65376a7c7403..5aa0cd78b14b 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -48,8 +48,6 @@ import {escapePathForRegex} from 'jest-regex-util'; import Resolver from 'jest-resolve'; import Snapshot = require('jest-snapshot'); import {createDirectory, deepCyclicCopy} from 'jest-util'; -import {run as cliRun} from './cli'; -import {options as cliOptions} from './cli/args'; import { createOutsideJestVmPath, decodePossibleOutsideJestVmPath, @@ -351,12 +349,12 @@ export default class Runtime { }); } - static runCLI(args?: Config.Argv, info?: Array): Promise { - return cliRun(args, info); + static async runCLI(): Promise { + throw new Error('The jest-runtime CLI has been moved into jest-repl'); } - static getCLIOptions(): typeof cliOptions { - return cliOptions; + static getCLIOptions(): never { + throw new Error('The jest-runtime CLI has been moved into jest-repl'); } // unstable as it should be replaced by https://github.com/nodejs/modules/issues/393, and we don't want people to use it diff --git a/packages/jest-runtime/tsconfig.json b/packages/jest-runtime/tsconfig.json index 1d0dc04b3ca7..f02568529755 100644 --- a/packages/jest-runtime/tsconfig.json +++ b/packages/jest-runtime/tsconfig.json @@ -5,7 +5,6 @@ "outDir": "build" }, "references": [ - {"path": "../jest-config"}, {"path": "../jest-console"}, {"path": "../jest-environment"}, {"path": "../jest-environment-node"}, diff --git a/yarn.lock b/yarn.lock index ab5ec7add888..de11fbb52785 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12047,12 +12047,17 @@ fsevents@~2.1.2: version: 0.0.0-use.local resolution: "jest-repl@workspace:packages/jest-repl" dependencies: + "@jest/console": ^26.6.2 + "@jest/environment": ^26.6.2 "@jest/test-utils": ^26.6.2 "@jest/transform": ^26.6.2 "@jest/types": ^26.6.2 "@types/yargs": ^15.0.0 + chalk: ^4.0.0 + execa: ^4.0.0 jest-config: ^26.6.3 jest-runtime: ^26.6.3 + jest-util: ^26.6.2 jest-validate: ^26.6.2 repl: ^0.1.3 yargs: ^16.0.3 @@ -12160,7 +12165,6 @@ fsevents@~2.1.2: exit: ^0.1.2 glob: ^7.1.3 graceful-fs: ^4.2.4 - jest-config: ^26.6.3 jest-environment-node: ^26.6.2 jest-haste-map: ^26.6.2 jest-message-util: ^26.6.2