From 6ce676a8477f783276dc64d7cfb2facdfcf04f6e Mon Sep 17 00:00:00 2001 From: Steven Hargrove Date: Thu, 13 Dec 2018 13:16:02 -0500 Subject: [PATCH] Support dashed args (#7497) * added dashed arg support to fix #7424 * update docs & changelog * fix dashed arg support tests * move changelog item to correct location, small edit to docs * use camelcase, filter dashed args on returns config --- CHANGELOG.md | 14 +++++ docs/CLI.md | 15 +++++ e2e/__tests__/supports-dashed-args.js | 63 +++++++++++++++++++ .../jest-cli/src/__tests__/cli/args.test.js | 13 ++++ packages/jest-cli/src/cli/index.js | 19 +++++- packages/jest-validate/package.json | 1 + .../jest-validate/src/validate_cli_options.js | 12 +++- 7 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 e2e/__tests__/supports-dashed-args.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c862aebb7b9..0b8886e473e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,20 @@ - `[jest-runtime]` Fix missing coverage when using negative glob pattern in `testMatch` ([#7170](https://github.com/facebook/jest/pull/7170)) - `[*]` Ensure `maxWorkers` is at least 1 (was 0 in some cases where there was only 1 CPU) ([#7182](https://github.com/facebook/jest/pull/7182)) - `[jest-runtime]` Fix transform cache invalidation when requiring a test file from multiple projects ([#7186](https://github.com/facebook/jest/pull/7186)) +- `[jest-changed-files]` Return correctly the changed files when using `lastCommit=true` on Mercurial repositories ([#7228](https://github.com/facebook/jest/pull/7228)) +- `[babel-jest]` Cache includes babel environment variables ([#7239](https://github.com/facebook/jest/pull/7239)) +- `[jest-config]` Use strings instead of `RegExp` instances in normalized configuration ([#7251](https://github.com/facebook/jest/pull/7251)) +- `[jest-circus]` Make sure to display real duration even if time is mocked ([#7264](https://github.com/facebook/jest/pull/7264)) +- `[expect]` Improves the failing message for `toStrictEqual` matcher. ([#7224](https://github.com/facebook/jest/pull/7224)) +- `[jest-resolve]` Fix not being able to resolve path to mapped file with custom platform ([#7312](https://github.com/facebook/jest/pull/7312)) +- `[jest-message-util]` Improve parsing of error messages for unusually formatted stack traces ([#7319](https://github.com/facebook/jest/pull/7319)) +- `[jest-runtime]` Ensure error message text is not lost on errors with code frames ([#7319](https://github.com/facebook/jest/pull/7319)) +- `[jest-haste-map]` Fix to resolve path that is start with words same as rootDir ([#7324](https://github.com/facebook/jest/pull/7324)) +- `[expect]` Fix toMatchObject matcher when used with `Object.create(null)` ([#7334](https://github.com/facebook/jest/pull/7334)) +- `[jest-haste-map]` Remove legacy condition for duplicate module detection ([#7333](https://github.com/facebook/jest/pull/7333)) +- `[jest-haste-map]` Fix `require` detection with trailing commas and ignore `import typeof` modules ([#7385](https://github.com/facebook/jest/pull/7385)) +- `[jest-cli]` Fix to set prettierPath via config file ([#7412](https://github.com/facebook/jest/pull/7412)) +- `[jest-cli]` Support dashed args ([#7497](https://github.com/facebook/jest/pull/7497)) ### Chore & Maintenance diff --git a/docs/CLI.md b/docs/CLI.md index 9c15b7273f59..4cf789db9a9d 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -81,6 +81,21 @@ you can use: npm test -- -u -t="ColorPicker" ``` +## Camelcase & dashed args support + +Jest supports both camelcase and dashed arg formats. The following examples will have equal result: + +```bash +jest --collect-coverage +jest --collectCoverage +``` + +Arguments can also be mixed: + +```bash +jest --update-snapshot --detectOpenHandles +``` + ## Options _Note: CLI options take precedence over values from the [Configuration](Configuration.md)._ diff --git a/e2e/__tests__/supports-dashed-args.js b/e2e/__tests__/supports-dashed-args.js new file mode 100644 index 000000000000..a0c18a22ebbe --- /dev/null +++ b/e2e/__tests__/supports-dashed-args.js @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018-present, Facebook, Inc. 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. + * + * @flow + */ + +'use strict'; + +import path from 'path'; +import runJest from '../runJest'; + +const consoleDir = path.resolve(__dirname, '../console'); +const eachDir = path.resolve(__dirname, '../each'); + +expect.addSnapshotSerializer({ + print: value => value, + test: received => typeof received === 'string', +}); + +test('works with passing tests', () => { + const result = runJest(eachDir, [ + 'success.test.js', + '--runInBand', + '--collect-coverage', + '--coverageReporters', + 'text-summary', + '--clear-mocks', + '--useStderr', + ]); + if (result.status !== 0) { + console.error(result.stderr); + } + expect(result.status).toBe(0); +}); + +test('throws error for unknown dashed & camelcase args', () => { + const result = runJest(consoleDir, [ + 'success.test.js', + '--runInBand', + '--collect-coverage', + '--coverageReporters', + 'text-summary', + '--clear-mocks', + '--doesNotExist', + '--also-does-not-exist', + '--useStderr', + ]); + expect(result.stderr).toMatchInlineSnapshot(` +● Unrecognized CLI Parameters: + + Following options were not recognized: + ["doesNotExist", "also-does-not-exist"] + + CLI Options Documentation: + https://jestjs.io/docs/en/cli.html + + +`); + expect(result.status).toBe(1); +}); diff --git a/packages/jest-cli/src/__tests__/cli/args.test.js b/packages/jest-cli/src/__tests__/cli/args.test.js index 88f3faf1c4c5..88d16dc43591 100644 --- a/packages/jest-cli/src/__tests__/cli/args.test.js +++ b/packages/jest-cli/src/__tests__/cli/args.test.js @@ -10,6 +10,7 @@ import type {Argv} from 'types/Argv'; import {check} from '../../cli/args'; +import {buildArgv} from '../../cli'; describe('check', () => { it('returns true if the arguments are valid', () => { @@ -59,3 +60,15 @@ describe('check', () => { ); }); }); + +describe('buildArgv', () => { + it('should return only camelcased args ', () => { + const mockProcessArgv = jest + .spyOn(process.argv, 'slice') + .mockImplementation(() => ['--clear-mocks']); + const actual = buildArgv(null); + expect(actual).not.toHaveProperty('clear-mocks'); + expect(actual).toHaveProperty('clearMocks', true); + mockProcessArgv.mockRestore(); + }); +}); diff --git a/packages/jest-cli/src/cli/index.js b/packages/jest-cli/src/cli/index.js index 889a35f77808..1ac1e6937a01 100644 --- a/packages/jest-cli/src/cli/index.js +++ b/packages/jest-cli/src/cli/index.js @@ -35,6 +35,7 @@ import logDebugMessages from '../lib/log_debug_messages'; export async function run(maybeArgv?: Argv, project?: Path) { try { + // $FlowFixMe:`allow reduced return const argv: Argv = buildArgv(maybeArgv, project); if (argv.init) { @@ -169,8 +170,9 @@ const readResultsAndExit = ( } }; -const buildArgv = (maybeArgv: ?Argv, project: ?Path) => { - const argv: Argv = yargs(maybeArgv || process.argv.slice(2)) +export const buildArgv = (maybeArgv: ?Argv, project: ?Path) => { + const rawArgv: Argv | string[] = maybeArgv || process.argv.slice(2); + const argv: Argv = yargs(rawArgv) .usage(args.usage) .alias('help', 'h') .options(args.options) @@ -180,9 +182,20 @@ const buildArgv = (maybeArgv: ?Argv, project: ?Path) => { validateCLIOptions( argv, Object.assign({}, args.options, {deprecationEntries}), + // strip leading dashes + Array.isArray(rawArgv) + ? rawArgv.map(rawArgv => rawArgv.replace(/^--?/, '')) + : Object.keys(rawArgv), ); - return argv; + // strip dashed args + return Object.keys(argv).reduce((result, key) => { + if (!key.includes('-')) { + // $FlowFixMe:`allow reduced return + result[key] = argv[key]; + } + return result; + }, {}); }; const getProjectListFromCLIArgs = (argv, project: ?Path) => { diff --git a/packages/jest-validate/package.json b/packages/jest-validate/package.json index e9a5683cebec..c617373f42de 100644 --- a/packages/jest-validate/package.json +++ b/packages/jest-validate/package.json @@ -8,6 +8,7 @@ "license": "MIT", "main": "build/index.js", "dependencies": { + "camelcase": "^5.0.0", "chalk": "^2.0.1", "jest-get-type": "^22.1.0", "leven": "^2.1.0", diff --git a/packages/jest-validate/src/validate_cli_options.js b/packages/jest-validate/src/validate_cli_options.js index 28f3debff0bf..b7cc117145c0 100644 --- a/packages/jest-validate/src/validate_cli_options.js +++ b/packages/jest-validate/src/validate_cli_options.js @@ -10,6 +10,7 @@ import type {Argv} from 'types/Argv'; import chalk from 'chalk'; +import camelcase from 'camelcase'; import {createDidYouMeanMessage, format, ValidationError} from './utils'; import {deprecationWarning} from './deprecated'; import defaultConfig from './default_config'; @@ -65,7 +66,11 @@ const logDeprecatedOptions = ( }); }; -export default function validateCLIOptions(argv: Argv, options: Object) { +export default function validateCLIOptions( + argv: Argv, + options: Object, + rawArgv: string[] = [], +) { const yargsSpecialOptions = ['$0', '_', 'help', 'h']; const deprecationEntries = options.deprecationEntries || {}; const allowedOptions = Object.keys(options).reduce( @@ -73,7 +78,10 @@ export default function validateCLIOptions(argv: Argv, options: Object) { new Set(yargsSpecialOptions), ); const unrecognizedOptions = Object.keys(argv).filter( - arg => !allowedOptions.has(arg), + arg => + !allowedOptions.has(camelcase(arg)) && + (!rawArgv.length || rawArgv.includes(arg)), + [], ); if (unrecognizedOptions.length) {