From cb2048940fc45548fd959a3c62471edbe1f0934f Mon Sep 17 00:00:00 2001 From: John Gee Date: Sat, 21 Sep 2019 17:19:23 +1200 Subject: [PATCH] Pass unknown to command:* to detect unknown options Co-authored-by: Case Larsen --- index.js | 2 +- tests/command.unknownOption.test.js | 85 +++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/command.unknownOption.test.js diff --git a/index.js b/index.js index ad5d82f4a..e16f3ebe1 100644 --- a/index.js +++ b/index.js @@ -754,7 +754,7 @@ Command.prototype.parseArgs = function(args, unknown) { if (this.listeners('command:' + name).length) { this.emit('command:' + args.shift(), args, unknown); } else { - this.emit('command:*', args); + this.emit('command:*', args, unknown); } } else { outputHelpIfNecessary(this, unknown); diff --git a/tests/command.unknownOption.test.js b/tests/command.unknownOption.test.js new file mode 100644 index 000000000..a4f571f68 --- /dev/null +++ b/tests/command.unknownOption.test.js @@ -0,0 +1,85 @@ +const commander = require('../'); + +// Checking for detection of unknown options, including regression tests for some past issues. + +describe('.version', () => { + // Optional. Use internal knowledge to suppress output to keep test output clean. + let consoleErrorSpy; + + beforeAll(() => { + consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { }); + }); + + afterEach(() => { + consoleErrorSpy.mockClear(); + }); + + afterAll(() => { + consoleErrorSpy.mockRestore(); + }); + + test('when specify unknown option with subcommand and action handler then error', () => { + const program = new commander.Command(); + program + .exitOverride() + .command('info') + .action(() => {}); + + let caughtErr; + try { + program.parse(['node', 'info', '--NONSENSE']); + } catch (err) { + caughtErr = err; + } + expect(caughtErr.code).toBe('commander.unknownOption'); + }); + + test('when specify unknown option with subcommand argument and action handler then error', () => { + const program = new commander.Command(); + program + .exitOverride() + .command('info ') + .action(() => {}); + + let caughtErr; + try { + program.parse(['node', 'test', 'info', 'a', '--NONSENSE']); + } catch (err) { + caughtErr = err; + } + expect(caughtErr.code).toBe('commander.unknownOption'); + }); + + test('when specify unknown option with program and action handler then error', () => { + const program = new commander.Command(); + program + .exitOverride() + .arguments('[file]') + .action(() => {}); + + let caughtErr; + try { + program.parse(['node', 'test', '--NONSENSE']); + } catch (err) { + caughtErr = err; + } + expect(caughtErr.code).toBe('commander.unknownOption'); + }); + + test('when specify unknown option with program argument and action handler then error', () => { + // Regression test from #965 + const program = new commander.Command(); + program + .exitOverride() + .arguments('[file]') + .action(() => {}); + + let caughtErr; + try { + program.parse(['node', 'test', 'info', 'a', '--NONSENSE']); + } catch (err) { + caughtErr = err; + } + expect(caughtErr.code).toBe('commander.unknownOption'); + }); +});