mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-12-10 11:26:24 +00:00
Improve infinito CLI global and full help:
- Add ANSI color fallback when colorama is missing - Refactor global help into print_global_help() and reuse for --help and --help-all - Enhance show_full_help_for_all() with colorful Subcommand/File headers - Extend unit tests for global help, child sound handling, and failure loop Reference: https://chatgpt.com/share/692e88de-39f4-800f-ab7f-5ac178698831/share/this-conversation
This commit is contained in:
@@ -146,6 +146,79 @@ class TestMainHelpers(unittest.TestCase):
|
||||
description = main.extract_description_via_help("/fake/path/empty.py")
|
||||
self.assertEqual(description, "-")
|
||||
|
||||
@mock.patch('main.extract_description_via_help')
|
||||
@mock.patch('main.format_command_help')
|
||||
@mock.patch('builtins.print')
|
||||
def test_print_global_help_uses_helpers_per_command(self, mock_print, mock_fmt, mock_extract):
|
||||
"""
|
||||
print_global_help() should call extract_description_via_help() and
|
||||
format_command_help() once per available command, with correct paths.
|
||||
"""
|
||||
cli_dir = "/tmp/cli"
|
||||
available = [
|
||||
(None, "rootcmd"),
|
||||
("meta/j2", "compiler"),
|
||||
]
|
||||
|
||||
mock_extract.return_value = "DESC"
|
||||
mock_fmt.side_effect = lambda name, desc, **kwargs: f"{name}:{desc}"
|
||||
|
||||
main.print_global_help(available, cli_dir)
|
||||
|
||||
# extract_description_via_help should be called with the correct .py paths
|
||||
expected_paths = [
|
||||
os.path.join(cli_dir, "rootcmd.py"),
|
||||
os.path.join(cli_dir, "meta", "j2", "compiler.py"),
|
||||
]
|
||||
called_paths = [call.args[0] for call in mock_extract.call_args_list]
|
||||
self.assertEqual(expected_paths, called_paths)
|
||||
|
||||
# format_command_help should be called for both commands, in order
|
||||
called_names = [call.args[0] for call in mock_fmt.call_args_list]
|
||||
self.assertEqual(["rootcmd", "compiler"], called_names)
|
||||
|
||||
@mock.patch('builtins.print')
|
||||
def test__play_in_child_failure_returns_false_and_prints_warning(self, mock_print):
|
||||
"""
|
||||
_play_in_child() should return False and print a diagnostic
|
||||
when the child exitcode is non-zero.
|
||||
"""
|
||||
|
||||
class FakeProcess:
|
||||
def __init__(self, target=None, args=None):
|
||||
self.exitcode = 1
|
||||
def start(self):
|
||||
pass
|
||||
def join(self):
|
||||
pass
|
||||
|
||||
with mock.patch('main.Process', FakeProcess):
|
||||
ok = main._play_in_child("play_warning_sound")
|
||||
|
||||
self.assertFalse(ok)
|
||||
self.assertTrue(
|
||||
any("[sound] child" in str(c.args[0]) for c in mock_print.call_args_list),
|
||||
"Expected a diagnostic print when exitcode != 0",
|
||||
)
|
||||
|
||||
@mock.patch('main._play_in_child')
|
||||
@mock.patch('main.time.sleep')
|
||||
def test_failure_with_warning_loop_no_signal_skips_sounds_and_exits(
|
||||
self, mock_sleep, mock_play
|
||||
):
|
||||
"""
|
||||
When no_signal=True, failure_with_warning_loop() should not call
|
||||
_play_in_child at all and should exit after the timeout.
|
||||
"""
|
||||
|
||||
# Simulate time.monotonic jumping past the timeout immediately
|
||||
with mock.patch('main.time.monotonic', side_effect=[0.0, 100.0]):
|
||||
with mock.patch('main.sys.exit', side_effect=SystemExit) as mock_exit:
|
||||
with self.assertRaises(SystemExit):
|
||||
main.failure_with_warning_loop(no_signal=True, sound_enabled=True, alarm_timeout=1)
|
||||
|
||||
mock_play.assert_not_called()
|
||||
mock_exit.assert_called() # ensure we attempted to exit
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user