@@ -384,6 +384,51 @@ def test_parser_attachment() -> None:
384384 assert root_subparsers .detach_parser ("fake" ) is None # type: ignore[attr-defined]
385385
386386
387+ def test_subcommand_attachment () -> None :
388+ # Attach a subcommand
389+ root_parser = Cmd2ArgumentParser (description = "root command" )
390+ root_subparsers = root_parser .add_subparsers ()
391+
392+ child_parser = Cmd2ArgumentParser (description = "child command" )
393+ root_parser .attach_subcommand (
394+ [],
395+ "child" ,
396+ child_parser ,
397+ help = "a child command" ,
398+ aliases = ["child_alias" ],
399+ )
400+
401+ # Verify the same parser instance was used
402+ assert root_subparsers ._name_parser_map ["child" ] is child_parser
403+ assert root_subparsers ._name_parser_map ["child_alias" ] is child_parser
404+
405+ # Verify an action with the help text exists
406+ child_action = None
407+ for action in root_subparsers ._choices_actions :
408+ if action .dest == "child" :
409+ child_action = action
410+ break
411+ assert child_action is not None
412+ assert child_action .help == "a child command"
413+
414+ # Detatch the subcommand
415+ detached_parser = root_parser .detach_subcommand ([], "child" )
416+
417+ # Verify subcommand and its aliases were removed
418+ assert detached_parser is child_parser
419+ assert "child" not in root_subparsers ._name_parser_map
420+ assert "child_alias" not in root_subparsers ._name_parser_map
421+
422+ # Verify the help text action was removed
423+ choices_actions = [action .dest for action in root_subparsers ._choices_actions ]
424+ assert "child" not in choices_actions
425+
426+ # Verify it raises a ValueError when subcommand does not exist
427+ expected_err = "Subcommand 'fake' not found"
428+ with pytest .raises (ValueError , match = expected_err ):
429+ assert root_parser .detach_subcommand ([], "fake" ) is None
430+
431+
387432def test_completion_items_as_choices (capsys ) -> None :
388433 """Test cmd2's patch to Argparse._check_value() which supports CompletionItems as choices.
389434 Choices are compared to CompletionItems.orig_value instead of the CompletionItem instance.
0 commit comments