Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move jest-runtime CLI into jest-repl #10016

Merged
merged 1 commit into from Nov 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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