diff --git a/Readme.md b/Readme.md index 22c2dc60e..c9a83fa1a 100644 --- a/Readme.md +++ b/Readme.md @@ -546,7 +546,7 @@ subcommand is specified ([example](./examples/defaultCommand.js)). You can add alternative names for a command with `.alias()`. ([example](./examples/alias.js)) -For safety, `.addCommand()` does not automatically copy the inherited settings from the parent command. There is a helper routine `.copyInheritedSettings()` for copying the settings when they are wanted. +For safety, `.addCommand()` does not automatically copy the inherited settings from the parent command. There is a helper routine `.copyInheritedSettings()` for copying the settings when they are wanted. The copying is done recursively, so the settings are inherited by the entire subcommand hierarchy. ### Command-arguments diff --git a/lib/command.js b/lib/command.js index 590a271dd..1550a47be 100644 --- a/lib/command.js +++ b/lib/command.js @@ -106,6 +106,10 @@ class Command extends EventEmitter { this._showHelpAfterError = sourceCommand._showHelpAfterError; this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError; + this.commands.forEach(command => { + command.copyInheritedSettings(this); + }); + return this; } diff --git a/tests/command.copySettings.test.js b/tests/command.copySettings.test.js index 79722d78b..a30dfb847 100644 --- a/tests/command.copySettings.test.js +++ b/tests/command.copySettings.test.js @@ -18,6 +18,28 @@ test('when add subcommand with .command() then calls copyInheritedSettings from expect(copySettingMock).toHaveBeenCalledWith(program); }); +test('when copyInheritedSettings on command with subcommand hierarchy then copies recursively', () => { + const source = new commander.Command(); + const cmd = new commander.Command(); + + const descendants = Array.from({ length: 4 }, (_, i) => ( + new commander.Command(String(i)) + )); + const parents = [cmd, cmd, descendants[0], descendants[1]]; + descendants.forEach((descendant, i) => { + descendant.copyInheritedSettings = jest.fn().mockImplementation( + descendant.copyInheritedSettings + ); + parents[i].addCommand(descendant); + }); + + cmd.copyInheritedSettings(source); + descendants.forEach((descendant, i) => { + const copySettingMock = descendant.copyInheritedSettings; + expect(copySettingMock).toHaveBeenCalledWith(parents[i]); + }); +}); + describe('copyInheritedSettings property tests', () => { test('when copyInheritedSettings then copies outputConfiguration(config)', () => { const source = new commander.Command();