Skip to content

Commit

Permalink
Move jest-runtime CLI into jest-repl
Browse files Browse the repository at this point in the history
Fixes #10011
  • Loading branch information
ghostd committed Nov 14, 2020
1 parent dbb1290 commit f5c0d8f
Show file tree
Hide file tree
Showing 20 changed files with 194 additions and 124 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Expand Up @@ -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/',
Expand Down
2 changes: 0 additions & 2 deletions packages/jest-core/src/__tests__/SearchSource.test.ts
Expand Up @@ -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,
]);
});
Expand Down
Expand Up @@ -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();
7 changes: 6 additions & 1 deletion packages/jest-repl/package.json
Expand Up @@ -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": {
Expand Down
49 changes: 49 additions & 0 deletions 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');
});
});
Expand Up @@ -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.');
Expand Down
10 changes: 10 additions & 0 deletions 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');
37 changes: 35 additions & 2 deletions packages/jest-repl/src/cli/args.ts
Expand Up @@ -7,12 +7,45 @@
*/

import type {Options} from 'yargs';
import Runtime from 'jest-runtime';

export const usage = 'Usage: $0 [--config=<pathToConfigFile>]';

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<string, Options> = {
...Runtime.getCLIOptions(),
...runtimeCLIOptions,
replname: {
alias: 'r',
description:
Expand Down
6 changes: 3 additions & 3 deletions packages/jest-repl/src/cli/index.ts
Expand Up @@ -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');

Expand All @@ -24,5 +24,5 @@ export = function (): void {

argv._ = [REPL_SCRIPT];

Runtime.runCLI(argv, [`Jest REPL v${VERSION}`]);
runtimeCLI(argv, [`Jest REPL v${VERSION}`]);
};
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down
Expand Up @@ -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;
6 changes: 5 additions & 1 deletion packages/jest-repl/tsconfig.json
Expand Up @@ -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"}
]
}
1 change: 0 additions & 1 deletion packages/jest-runtime/package.json
Expand Up @@ -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",
Expand Down
73 changes: 68 additions & 5 deletions packages/jest-runtime/src/__mocks__/createRuntime.js
Expand Up @@ -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>', 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,
Expand All @@ -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;
Expand Down

0 comments on commit f5c0d8f

Please sign in to comment.