Skip to content

Commit 9cedde5

Browse files
committed
fix(webpack-cli): throw error for invalid args with HelpGroup
1 parent d268e13 commit 9cedde5

File tree

9 files changed

+87
-81
lines changed

9 files changed

+87
-81
lines changed

packages/webpack-cli/lib/groups/HelpGroup.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ const chalk = require('chalk');
22
const { core, commands } = require('../utils/cli-flags');
33
const commandLineUsage = require('command-line-usage');
44

5+
const [, , ...rawArgs] = process.argv;
6+
const commandsUsed = rawArgs.filter((val) => commands.find(({ name }) => name === val));
7+
const flagsUsed = rawArgs.filter((val) => core.find(({ name }) => name === val.slice(2)));
8+
const argsUsed = [...commandsUsed, ...flagsUsed];
9+
const invalidArgs = rawArgs.filter((e) => !argsUsed.includes(e) && !e.includes('--color') && e !== 'version' && e !== 'help' && e !== '-v');
10+
511
class HelpGroup {
612
outputHelp(isCommand = true, subject) {
7-
if (subject) {
13+
if (subject && invalidArgs.length === 0) {
814
const info = isCommand ? commands : core;
915
// Contains object with details about given subject
1016
const options = info.find((commandOrFlag) => {
@@ -34,20 +40,20 @@ class HelpGroup {
3440
});
3541
process.stdout.write(flags);
3642
}
43+
} else if (invalidArgs.length > 0) {
44+
console.error(chalk.red(`\nError: Invalid Option '${invalidArgs[0]}'.`));
45+
console.info(chalk.cyan('Run webpack --help to see available commands and arguments.\n'));
46+
process.exit(-2);
3747
} else {
3848
process.stdout.write(this.run().outputOptions.help);
3949
}
4050
process.stdout.write('\n Made with ♥️ by the webpack team \n');
4151
}
4252

4353
outputVersion(externalPkg) {
44-
const commandsUsed = () => {
45-
return process.argv.filter((val) => commands.find(({ name }) => name === val));
46-
};
47-
48-
if (externalPkg && commandsUsed().length === 1) {
54+
if (externalPkg && commandsUsed.length === 1) {
4955
try {
50-
if (commandsUsed().includes(externalPkg.name)) {
56+
if (commandsUsed.includes(externalPkg.name)) {
5157
const { name, version } = require(`@webpack-cli/${externalPkg.name}/package.json`);
5258
process.stdout.write(`\n${name} ${version}`);
5359
} else {
@@ -60,11 +66,17 @@ class HelpGroup {
6066
}
6167
}
6268

63-
if (commandsUsed().length > 1) {
69+
if (commandsUsed.length > 1) {
6470
console.error(chalk.red('\nYou provided multiple commands. Please use only one command at a time.\n'));
6571
process.exit();
6672
}
6773

74+
if (invalidArgs.length > 0) {
75+
console.error(chalk.red(`\nError: Invalid Option '${invalidArgs[0]}'.`));
76+
console.info(chalk.cyan('Run webpack --help to see available commands and arguments.\n'));
77+
process.exit(-2);
78+
}
79+
6880
const pkgJSON = require('../../package.json');
6981
const webpack = require('webpack');
7082
process.stdout.write(`\nwebpack-cli ${pkgJSON.version}`);

test/help/help-commands.test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ const { run } = require('../utils/test-utils');
44
const helpHeader = 'The build tool for modern web applications';
55

66
describe('commands help', () => {
7-
it('shows default help with invalid command', () => {
8-
const { stdout, stderr } = run(__dirname, ['--help', 'myCommand'], false);
9-
expect(stdout).toContain(helpHeader);
10-
expect(stderr).toHaveLength(0);
7+
it('throws error for invalid command with --help flag', () => {
8+
const { stderr, stdout } = run(__dirname, ['--help', 'myCommand'], false);
9+
expect(stderr).toContain(`Error: Invalid Option 'myCommand'`);
10+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
1111
});
12-
it('shows command help with valid command', () => {
13-
const { stdout, stderr } = run(__dirname, ['--help', 'init'], false);
14-
expect(stdout).not.toContain(helpHeader);
15-
expect(stdout).toContain('webpack init | init <scaffold>');
16-
expect(stderr).toHaveLength(0);
12+
13+
it('throws error for invalid command with help command', () => {
14+
const { stderr, stdout } = run(__dirname, ['help', 'myCommand'], false);
15+
expect(stderr).toContain(`Error: Invalid Option 'myCommand'`);
16+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
1717
});
1818

1919
it('gives precedence to earlier command in case of multiple commands', () => {

test/help/help-flags.test.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@ const { run } = require('../utils/test-utils');
44
const helpHeader = 'The build tool for modern web applications';
55

66
describe('commands help', () => {
7-
it('shows default help with invalid flag', () => {
7+
it('throws error for invalid flag with --help flag', () => {
88
const { stdout, stderr } = run(__dirname, ['--help', '--my-flag'], false);
9-
expect(stdout).toContain(helpHeader);
10-
expect(stderr).toHaveLength(0);
9+
expect(stderr).toContain(`Error: Invalid Option '--my-flag'`);
10+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
11+
});
12+
13+
it('throws error for invalid flag with help command', () => {
14+
const { stderr, stdout } = run(__dirname, ['help', '--my-flag'], false);
15+
expect(stderr).toContain(`Error: Invalid Option '--my-flag'`);
16+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
1117
});
18+
1219
it('shows flag help with valid flag', () => {
1320
const { stdout, stderr } = run(__dirname, ['--help', '--merge'], false);
1421
expect(stdout).not.toContain(helpHeader);

test/help/help-multi-args.test.js

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
'use strict';
22

33
const { run } = require('../utils/test-utils');
4-
const outputDescription = 'Output location of the file generated by webpack';
5-
const createDescription = 'Initialize a new webpack configuration';
6-
describe('help flag with multiple arguments', () => {
7-
it('outputs info with dashed syntax', () => {
8-
const { stdout, stderr } = run(__dirname, ['--help', '--target', 'browser']);
9-
expect(stdout).toContain(outputDescription);
10-
expect(stderr).toHaveLength(0);
11-
});
12-
13-
it('outputs info with multiple arguments using dashes and with precedence', () => {
14-
const { stdout, stderr } = run(__dirname, ['--target', 'browser', '--help']);
15-
expect(stdout).toContain(outputDescription);
16-
expect(stderr).toHaveLength(0);
17-
});
4+
const { commands } = require('../../packages/webpack-cli/lib/utils/cli-flags');
5+
const helpHeader = 'The build tool for modern web applications';
186

19-
it('outputs info with multiple commands and with precedence', () => {
20-
const { stdout, stderr } = run(__dirname, ['init', 'help']);
21-
expect(stdout).toContain(createDescription);
22-
expect(stderr).toHaveLength(0);
7+
describe('help cmd with multiple arguments', () => {
8+
commands.forEach((cmd) => {
9+
it(`shows cmd help with ${cmd.name}`, () => {
10+
const { stdout, stderr } = run(__dirname, ['--help', `${cmd.name}`], false);
11+
expect(stdout).not.toContain(helpHeader);
12+
expect(stdout).toContain(`${cmd.name}`);
13+
expect(stdout).toContain(`${cmd.usage}`);
14+
expect(stdout).toContain(`${cmd.description}`);
15+
expect(stderr).toHaveLength(0);
16+
});
2317
});
2418
});

test/help/help-single-arg.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe('single help flag', () => {
1818
expect(stdout).toContain(example);
1919
expect(stderr).toHaveLength(0);
2020
});
21+
2122
it('outputs help info with command syntax', () => {
2223
const { stdout, stderr } = run(__dirname, ['help'], false);
2324
expect(stdout).toContain(helpHeader);

test/version/version-external-packages.test.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,41 @@ const cliPkgJSON = require('../../packages/webpack-cli/package.json');
99

1010
describe('version flag with external packages', () => {
1111
it('outputs version with init', () => {
12-
const { stdout, stderr } = run(__dirname, ['init', '--version']);
12+
const { stdout, stderr } = run(__dirname, ['init', '--version'], false);
1313
expect(stdout).toContain(initPkgJSON.version);
1414
expect(stdout).toContain(cliPkgJSON.version);
1515
expect(stderr).toHaveLength(0);
1616
});
1717

1818
it('outputs version with info', () => {
19-
const { stdout, stderr } = run(__dirname, ['info', '--version']);
19+
const { stdout, stderr } = run(__dirname, ['info', '--version'], false);
2020
expect(stdout).toContain(infoPkgJSON.version);
2121
expect(stdout).toContain(cliPkgJSON.version);
2222
expect(stderr).toHaveLength(0);
2323
});
2424

2525
it('outputs version with serve', () => {
26-
const { stdout, stderr } = run(__dirname, ['serve', '--version']);
26+
const { stdout, stderr } = run(__dirname, ['serve', '--version'], false);
2727
expect(stdout).toContain(servePkgJSON.version);
2828
expect(stdout).toContain(cliPkgJSON.version);
2929
expect(stderr).toHaveLength(0);
3030
});
3131

3232
it('outputs version with migrate', () => {
33-
const { stdout, stderr } = run(__dirname, ['migrate', '--version']);
33+
const { stdout, stderr } = run(__dirname, ['migrate', '--version'], false);
3434
expect(stdout).toContain(migratePkgJSON.version);
3535
expect(stdout).toContain(cliPkgJSON.version);
3636
expect(stderr).toHaveLength(0);
3737
});
3838

3939
it(' should throw error for multiple commands', () => {
40-
const { stderr } = run(__dirname, ['init', 'migrate', '--version']);
40+
const { stderr } = run(__dirname, ['init', 'migrate', '--version'], false);
4141
expect(stderr).toContain('You provided multiple commands.');
4242
});
43+
44+
it(' should throw error if invalid argument is present', () => {
45+
const { stderr, stdout } = run(__dirname, ['init', 'abc', '--version']);
46+
expect(stderr).toContain(`Error: Invalid Option 'abc'`);
47+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
48+
});
4349
});

test/version/version-multi-args.test.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@ const { run } = require('../utils/test-utils');
44
const pkgJSON = require('../../packages/webpack-cli/package.json');
55

66
describe('version flag with multiple arguments', () => {
7-
it('outputs version with mixed syntax', () => {
8-
const { stdout, stderr } = run(__dirname, ['--version', '--target', 'browser']);
9-
expect(stdout).toContain(pkgJSON.version);
10-
expect(stderr).toHaveLength(0);
11-
});
12-
137
it('does not output version with help command', () => {
14-
const { stdout, stderr } = run(__dirname, ['version', 'help']);
8+
const { stdout, stderr } = run(__dirname, ['version', 'help'], false);
159
expect(stdout).not.toContain(pkgJSON.version);
1610

1711
const uniqueIdentifier = 'Made with ♥️ by the webpack team';
@@ -20,17 +14,32 @@ describe('version flag with multiple arguments', () => {
2014
});
2115

2216
it('does not output version with help dashed', () => {
23-
const { stdout, stderr } = run(__dirname, ['version', '--help']);
17+
const { stdout, stderr } = run(__dirname, ['version', '--help'], false);
2418
expect(stdout).not.toContain(pkgJSON.version);
2519

2620
const uniqueIdentifier = 'Made with ♥️ by the webpack team';
2721
expect(stdout).toContain(uniqueIdentifier);
2822
expect(stderr).toHaveLength(0);
2923
});
3024

31-
it('outputs version with multiple dashed args and has precedence', () => {
32-
const { stdout, stderr } = run(__dirname, ['--target', 'browser', '--version']);
33-
expect(stdout).toContain(pkgJSON.version);
34-
expect(stderr).toHaveLength(0);
25+
it('throws error if invalid arg is passed with version command', () => {
26+
const { stdout, stderr } = run(__dirname, ['version', 'abc'], false);
27+
expect(stdout).not.toContain(pkgJSON.version);
28+
expect(stderr).toContain(`Error: Invalid Option 'abc'`);
29+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
30+
});
31+
32+
it('throws error if invalid arg is passed with --version flag', () => {
33+
const { stdout, stderr } = run(__dirname, ['--version', 'abc'], false);
34+
expect(stdout).not.toContain(pkgJSON.version);
35+
expect(stderr).toContain(`Error: Invalid Option 'abc'`);
36+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
37+
});
38+
39+
it('throws error if invalid arg is passed with -v alias', () => {
40+
const { stdout, stderr } = run(__dirname, ['-v', 'abc'], false);
41+
expect(stdout).not.toContain(pkgJSON.version);
42+
expect(stderr).toContain(`Error: Invalid Option 'abc'`);
43+
expect(stdout).toContain('Run webpack --help to see available commands and arguments');
3544
});
3645
});

test/version/version-single-arg.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ const pkgJSON = require('../../packages/webpack-cli/package.json');
55

66
describe('single version flag', () => {
77
it('outputs versions with command syntax', () => {
8-
const { stdout, stderr } = run(__dirname, ['version']);
8+
const { stdout, stderr } = run(__dirname, ['version'], false);
99
expect(stdout).toContain(pkgJSON.version);
1010
expect(stderr).toHaveLength(0);
1111
});
1212

1313
it('outputs versions with dashed syntax', () => {
14-
const { stdout, stderr } = run(__dirname, ['--version']);
14+
const { stdout, stderr } = run(__dirname, ['--version'], false);
1515
expect(stdout).toContain(pkgJSON.version);
1616
expect(stderr).toHaveLength(0);
1717
});
1818

1919
it('outputs versions with alias syntax', () => {
20-
const { stdout, stderr } = run(__dirname, ['-v']);
20+
const { stdout, stderr } = run(__dirname, ['-v'], false);
2121
expect(stdout).toContain(pkgJSON.version);
2222
expect(stderr).toHaveLength(0);
2323
});

yarn.lock

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2415,16 +2415,6 @@
24152415
regexpp "^3.0.0"
24162416
tsutils "^3.17.1"
24172417

2418-
"@typescript-eslint/experimental-utils@2.26.0":
2419-
version "2.26.0"
2420-
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.26.0.tgz#063390c404d9980767d76274df386c0aa675d91d"
2421-
integrity sha512-RELVoH5EYd+JlGprEyojUv9HeKcZqF7nZUGSblyAw1FwOGNnmQIU8kxJ69fttQvEwCsX5D6ECJT8GTozxrDKVQ==
2422-
dependencies:
2423-
"@types/json-schema" "^7.0.3"
2424-
"@typescript-eslint/typescript-estree" "2.26.0"
2425-
eslint-scope "^5.0.0"
2426-
eslint-utils "^2.0.0"
2427-
24282418
"@typescript-eslint/experimental-utils@2.28.0":
24292419
version "2.28.0"
24302420
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d"
@@ -2445,19 +2435,6 @@
24452435
"@typescript-eslint/typescript-estree" "2.28.0"
24462436
eslint-visitor-keys "^1.1.0"
24472437

2448-
"@typescript-eslint/typescript-estree@2.26.0":
2449-
version "2.26.0"
2450-
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.26.0.tgz#d8132cf1ee8a72234f996519a47d8a9118b57d56"
2451-
integrity sha512-3x4SyZCLB4zsKsjuhxDLeVJN6W29VwBnYpCsZ7vIdPel9ZqLfIZJgJXO47MNUkurGpQuIBALdPQKtsSnWpE1Yg==
2452-
dependencies:
2453-
debug "^4.1.1"
2454-
eslint-visitor-keys "^1.1.0"
2455-
glob "^7.1.6"
2456-
is-glob "^4.0.1"
2457-
lodash "^4.17.15"
2458-
semver "^6.3.0"
2459-
tsutils "^3.17.1"
2460-
24612438
"@typescript-eslint/typescript-estree@2.28.0":
24622439
version "2.28.0"
24632440
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00"

0 commit comments

Comments
 (0)