From efe81e986a6dca5cc9b72a5c9312dc21409f65b1 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Sun, 3 Jan 2021 21:24:44 +0300 Subject: [PATCH] fix: double commands output in help (#2298) --- packages/webpack-cli/__tests__/CLI.test.js | 106 +++++++++++++++++++++ packages/webpack-cli/lib/webpack-cli.js | 22 +++-- test/help/help.test.js | 18 ++++ 3 files changed, 137 insertions(+), 9 deletions(-) diff --git a/packages/webpack-cli/__tests__/CLI.test.js b/packages/webpack-cli/__tests__/CLI.test.js index cf64bbf55b0..99cae68b35e 100644 --- a/packages/webpack-cli/__tests__/CLI.test.js +++ b/packages/webpack-cli/__tests__/CLI.test.js @@ -9,6 +9,8 @@ describe('CLI API', () => { describe('makeCommand', () => { it('should make command', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand({ name: 'command' }, [], (program) => { expect(program.opts()).toEqual({}); @@ -19,6 +21,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option by default', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -40,6 +44,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -62,6 +68,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option and negative value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -85,6 +93,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option and negative value #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -108,6 +118,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option and negative value #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -131,6 +143,8 @@ describe('CLI API', () => { }); it('should make command with Boolean option with default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -154,6 +168,8 @@ describe('CLI API', () => { }); it('should make command with String option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -176,6 +192,8 @@ describe('CLI API', () => { }); it('should make command with String option with alias', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -199,6 +217,8 @@ describe('CLI API', () => { }); it('should make command with String option with default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -222,6 +242,8 @@ describe('CLI API', () => { }); it('should make command with String option with default value #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -245,6 +267,8 @@ describe('CLI API', () => { }); it('should make command with String option using "=" syntax', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -267,6 +291,8 @@ describe('CLI API', () => { }); it('should make command with multiple String option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -290,6 +316,8 @@ describe('CLI API', () => { }); it('should make command with multiple String option with default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -314,6 +342,8 @@ describe('CLI API', () => { }); it('should make command with multiple String option with default value #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -338,6 +368,8 @@ describe('CLI API', () => { }); it('should make command with multiple String option #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -361,6 +393,8 @@ describe('CLI API', () => { }); it('should make command with Number option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -383,6 +417,8 @@ describe('CLI API', () => { }); it('should make command with Number option with default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -406,6 +442,8 @@ describe('CLI API', () => { }); it('should make command with multiple Number option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -429,6 +467,8 @@ describe('CLI API', () => { }); it('should make command with multiple Number option and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -453,6 +493,8 @@ describe('CLI API', () => { }); it('should make command with multiple Number option and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -477,6 +519,8 @@ describe('CLI API', () => { }); it('should make command with custom function type', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -501,6 +545,8 @@ describe('CLI API', () => { }); it('should make command with custom function type and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -526,6 +572,8 @@ describe('CLI API', () => { }); it('should make command with multiple custom function type', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -551,6 +599,8 @@ describe('CLI API', () => { }); it('should make command with multiple custom function type and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -577,6 +627,8 @@ describe('CLI API', () => { }); it('should make command with multiple custom function type and default value #2', async (done) => { + cli.program.commands = []; + let skipDefault = true; const command = await cli.makeCommand( @@ -610,6 +662,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and String option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -632,6 +686,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and String option #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -654,6 +710,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and String option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -677,6 +735,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and String option #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -700,6 +760,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and String option and negative', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -723,6 +785,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and String option and negative #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -746,6 +810,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and String option and negative #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -769,6 +835,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number option', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -791,6 +859,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number option #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -813,6 +883,8 @@ describe('CLI API', () => { }); it('should make command with array Boolean type', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -835,6 +907,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -857,6 +931,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -879,6 +955,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -901,6 +979,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -924,6 +1004,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type and default value #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -947,6 +1029,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type and default value #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -970,6 +1054,8 @@ describe('CLI API', () => { }); it('should make command with Boolean and Number and String type and default value #4', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -993,6 +1079,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String type', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1016,6 +1104,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String type #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1039,6 +1129,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String type #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1062,6 +1154,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String type #4', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1085,6 +1179,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String type #5', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1108,6 +1204,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String and default value', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1132,6 +1230,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String and default value #2', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1156,6 +1256,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String and default value #3', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1180,6 +1282,8 @@ describe('CLI API', () => { }); it('should make command with multiple Boolean and Number and String and default value #4', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', @@ -1204,6 +1308,8 @@ describe('CLI API', () => { }); it('should make command with array of unknown types', async (done) => { + cli.program.commands = []; + const command = await cli.makeCommand( { name: 'command', diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index df8649fba1a..34e6f406c6e 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -30,6 +30,14 @@ class WebpackCLI { } async makeCommand(commandOptions, options, action) { + const alreadyLoaded = this.program.commands.find( + (command) => command.name() === commandOptions.name || command.alias() === commandOptions.alias, + ); + + if (alreadyLoaded) { + return; + } + const command = this.program.command(commandOptions.name, { noHelp: commandOptions.noHelp, hidden: commandOptions.hidden, @@ -551,15 +559,11 @@ class WebpackCLI { }; if (isGlobal) { - const commandsToLoad = [] - .concat(bundleCommandOptions) - .concat(helpCommandOptions) - .concat(versionCommandOptions) - .concat(externalBuiltInCommandsInfo); - - for (const commandToLoad of commandsToLoad) { - await loadCommandByName(commandToLoad.name); - } + await Promise.all( + knownCommands.map((knownCommand) => { + return loadCommandByName(knownCommand.name); + }), + ); const bundleCommand = this.program.commands.find( (command) => command.name() === bundleCommandOptions.name || command.alias() === bundleCommandOptions.alias, diff --git a/test/help/help.test.js b/test/help/help.test.js index d446a20947c..15126bb04bc 100644 --- a/test/help/help.test.js +++ b/test/help/help.test.js @@ -19,6 +19,15 @@ describe('help', () => { expect(stdout).not.toContain('--cache-type'); // verbose expect(stdout).toContain('Global options:'); expect(stdout).toContain('Commands:'); + expect(stdout.match(/bundle\|b/g)).toHaveLength(1); + expect(stdout.match(/version\|v/g)).toHaveLength(1); + expect(stdout.match(/help\|h/g)).toHaveLength(1); + expect(stdout.match(/serve\|s/g)).toHaveLength(1); + expect(stdout.match(/info\|i/g)).toHaveLength(1); + expect(stdout.match(/init\|c/g)).toHaveLength(1); + expect(stdout.match(/loader\|l/g)).toHaveLength(1); + expect(stdout.match(/migrate\|m/g)).toHaveLength(1); + expect(stdout.match(/plugin\|p/g)).toHaveLength(1); expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); // TODO buggy on windows @@ -41,6 +50,15 @@ describe('help', () => { expect(stdout).toContain('Global options:'); expect(stdout).toContain('Commands:'); + expect(stdout.match(/bundle\|b/g)).toHaveLength(1); + expect(stdout.match(/version\|v/g)).toHaveLength(1); + expect(stdout.match(/help\|h/g)).toHaveLength(1); + expect(stdout.match(/serve\|s/g)).toHaveLength(1); + expect(stdout.match(/info\|i/g)).toHaveLength(1); + expect(stdout.match(/init\|c/g)).toHaveLength(1); + expect(stdout.match(/loader\|l/g)).toHaveLength(1); + expect(stdout.match(/migrate\|m/g)).toHaveLength(1); + expect(stdout.match(/plugin\|p/g)).toHaveLength(1); expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.');