diff options
Diffstat (limited to 'tests/test_cmd2.py')
-rwxr-xr-x | tests/test_cmd2.py | 351 |
1 files changed, 290 insertions, 61 deletions
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 2f24f4d7..ae911474 100755 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -40,15 +40,19 @@ def CreateOutsimApp(): c.stdout = utils.StdSim(c.stdout) return c + @pytest.fixture def outsim_app(): return CreateOutsimApp() + def test_version(base_app): assert cmd2.__version__ + def test_not_in_main_thread(base_app, capsys): import threading + cli_thread = threading.Thread(name='cli_thread', target=base_app.cmdloop) cli_thread.start() @@ -56,15 +60,18 @@ def test_not_in_main_thread(base_app, capsys): out, err = capsys.readouterr() assert "cmdloop must be run in the main thread" in err + def test_empty_statement(base_app): out, err = run_cmd(base_app, '') expected = normalize('') assert out == expected + def test_base_help(base_app): out, err = run_cmd(base_app, 'help') verify_help_text(base_app, out) + def test_base_help_verbose(base_app): out, err = run_cmd(base_app, 'help -v') verify_help_text(base_app, out) @@ -78,6 +85,7 @@ def test_base_help_verbose(base_app): verify_help_text(base_app, out) assert ':param' not in ''.join(out) + def test_base_argparse_help(base_app): # Verify that "set -h" gives the same output as "help set" and that it starts in a way that makes sense out1, err1 = run_cmd(base_app, 'set -h') @@ -88,21 +96,25 @@ def test_base_argparse_help(base_app): assert out1[1] == '' assert out1[2].startswith('Set a settable parameter') + def test_base_invalid_option(base_app): out, err = run_cmd(base_app, 'set -z') assert err[0] == 'Usage: set [-h] [-v] [param] [value]' assert 'Error: unrecognized arguments: -z' in err[1] + def test_base_shortcuts(base_app): out, err = run_cmd(base_app, 'shortcuts') expected = normalize(SHORTCUTS_TXT) assert out == expected + def test_command_starts_with_shortcut(): with pytest.raises(ValueError) as excinfo: app = cmd2.Cmd(shortcuts={'help': 'fake'}) assert "Invalid command name 'help'" in str(excinfo.value) + def test_base_show(base_app): # force editor to be 'vim' so test is repeatable across platforms base_app.editor = 'vim' @@ -121,30 +133,37 @@ def test_base_show_long(base_app): def test_set(base_app): out, err = run_cmd(base_app, 'set quiet True') - expected = normalize(""" + expected = normalize( + """ quiet - was: False now: True -""") +""" + ) assert out == expected out, err = run_cmd(base_app, 'set quiet') assert out == ['quiet: True'] + def test_set_val_empty(base_app): base_app.editor = "fake" out, err = run_cmd(base_app, 'set editor ""') assert base_app.editor == '' + def test_set_val_is_flag(base_app): base_app.editor = "fake" out, err = run_cmd(base_app, 'set editor "-h"') assert base_app.editor == '-h' + def test_set_not_supported(base_app): out, err = run_cmd(base_app, 'set qqq True') - expected = normalize(""" + expected = normalize( + """ Parameter 'qqq' not supported (type 'set' for list of parameters). -""") +""" + ) assert err == expected @@ -155,15 +174,18 @@ def test_set_no_settables(base_app): assert err == expected -@pytest.mark.parametrize('new_val, is_valid, expected', [ - (ansi.STYLE_NEVER, True, ansi.STYLE_NEVER), - ('neVeR', True, ansi.STYLE_NEVER), - (ansi.STYLE_TERMINAL, True, ansi.STYLE_TERMINAL), - ('TeRMInal', True, ansi.STYLE_TERMINAL), - (ansi.STYLE_ALWAYS, True, ansi.STYLE_ALWAYS), - ('AlWaYs', True, ansi.STYLE_ALWAYS), - ('invalid', False, ansi.STYLE_TERMINAL), -]) +@pytest.mark.parametrize( + 'new_val, is_valid, expected', + [ + (ansi.STYLE_NEVER, True, ansi.STYLE_NEVER), + ('neVeR', True, ansi.STYLE_NEVER), + (ansi.STYLE_TERMINAL, True, ansi.STYLE_TERMINAL), + ('TeRMInal', True, ansi.STYLE_TERMINAL), + (ansi.STYLE_ALWAYS, True, ansi.STYLE_ALWAYS), + ('AlWaYs', True, ansi.STYLE_ALWAYS), + ('invalid', False, ansi.STYLE_TERMINAL), + ], +) def test_set_allow_style(base_app, new_val, is_valid, expected): # Initialize allow_style for this test ansi.allow_style = ansi.STYLE_TERMINAL @@ -190,18 +212,22 @@ class OnChangeHookApp(cmd2.Cmd): """Runs when quiet is changed via set command""" self.poutput("You changed " + name) + @pytest.fixture def onchange_app(): app = OnChangeHookApp() return app + def test_set_onchange_hook(onchange_app): out, err = run_cmd(onchange_app, 'set quiet True') - expected = normalize(""" + expected = normalize( + """ quiet - was: False now: True You changed quiet -""") +""" + ) assert out == expected @@ -212,6 +238,7 @@ def test_base_shell(base_app, monkeypatch): assert out == [] assert m.called + def test_shell_last_result(base_app): base_app.last_result = None run_cmd(base_app, 'shell fake') @@ -220,11 +247,7 @@ def test_shell_last_result(base_app): def test_shell_manual_call(base_app): # Verifies crash from Issue #986 doesn't happen - cmds = [ - 'echo "hi"', - 'echo "there"', - 'echo "cmd2!"' - ] + cmds = ['echo "hi"', 'echo "there"', 'echo "cmd2!"'] cmd = ';'.join(cmds) base_app.do_shell(cmd) @@ -299,31 +322,37 @@ def test_run_script(base_app, request): assert script_out == manual_out assert script_err == manual_err + def test_run_script_with_empty_args(base_app): out, err = run_cmd(base_app, 'run_script') assert "the following arguments are required" in err[1] + def test_run_script_with_nonexistent_file(base_app, capsys): out, err = run_cmd(base_app, 'run_script does_not_exist.txt') assert "does not exist" in err[0] + def test_run_script_with_directory(base_app, request): test_dir = os.path.dirname(request.module.__file__) out, err = run_cmd(base_app, 'run_script {}'.format(test_dir)) assert "is not a file" in err[0] + def test_run_script_with_empty_file(base_app, request): test_dir = os.path.dirname(request.module.__file__) filename = os.path.join(test_dir, 'scripts', 'empty.txt') out, err = run_cmd(base_app, 'run_script {}'.format(filename)) assert not out and not err + def test_run_script_with_binary_file(base_app, request): test_dir = os.path.dirname(request.module.__file__) filename = os.path.join(test_dir, 'scripts', 'binary.bin') out, err = run_cmd(base_app, 'run_script {}'.format(filename)) assert "is not an ASCII or UTF-8 encoded text file" in err[0] + def test_run_script_with_python_file(base_app, request): m = mock.MagicMock(name='input', return_value='2') builtins.input = m @@ -333,6 +362,7 @@ def test_run_script_with_python_file(base_app, request): out, err = run_cmd(base_app, 'run_script {}'.format(filename)) assert "appears to be a Python file" in err[0] + def test_run_script_with_utf8_file(base_app, request): test_dir = os.path.dirname(request.module.__file__) filename = os.path.join(test_dir, 'scripts', 'utf8.txt') @@ -360,6 +390,7 @@ def test_run_script_with_utf8_file(base_app, request): assert script_out == manual_out assert script_err == manual_err + def test_run_script_nested_run_scripts(base_app, request): # Verify that running a script with nested run_script commands works correctly, # and runs the nested script commands in the correct order. @@ -371,43 +402,48 @@ def test_run_script_nested_run_scripts(base_app, request): run_cmd(base_app, initial_run) # Check that the right commands were executed. - expected = """ + expected = ( + """ %s _relative_run_script precmds.txt set allow_style Always help shortcuts _relative_run_script postcmds.txt -set allow_style Never""" % initial_run +set allow_style Never""" + % initial_run + ) out, err = run_cmd(base_app, 'history -s') assert out == normalize(expected) + def test_runcmds_plus_hooks(base_app, request): test_dir = os.path.dirname(request.module.__file__) prefilepath = os.path.join(test_dir, 'scripts', 'precmds.txt') postfilepath = os.path.join(test_dir, 'scripts', 'postcmds.txt') - base_app.runcmds_plus_hooks(['run_script ' + prefilepath, - 'help', - 'shortcuts', - 'run_script ' + postfilepath]) + base_app.runcmds_plus_hooks(['run_script ' + prefilepath, 'help', 'shortcuts', 'run_script ' + postfilepath]) expected = """ -run_script %s +run_script {} set allow_style Always help shortcuts -run_script %s -set allow_style Never""" % (prefilepath, postfilepath) +run_script {} +set allow_style Never""".format( + prefilepath, postfilepath, + ) out, err = run_cmd(base_app, 'history -s') assert out == normalize(expected) + def test_runcmds_plus_hooks_ctrl_c(base_app, capsys): """Test Ctrl-C while in runcmds_plus_hooks""" import types def do_keyboard_interrupt(self, _): raise KeyboardInterrupt('Interrupting this command') + setattr(base_app, 'do_keyboard_interrupt', types.MethodType(do_keyboard_interrupt, base_app)) # Default behavior is to stop command loop on Ctrl-C @@ -424,6 +460,7 @@ def test_runcmds_plus_hooks_ctrl_c(base_app, capsys): assert not err assert len(base_app.history) == 3 + def test_relative_run_script(base_app, request): test_dir = os.path.dirname(request.module.__file__) filename = os.path.join(test_dir, 'script.txt') @@ -451,6 +488,7 @@ def test_relative_run_script(base_app, request): assert script_out == manual_out assert script_err == manual_err + @pytest.mark.parametrize('file_name', odd_file_names) def test_relative_run_script_with_odd_file_names(base_app, file_name, monkeypatch): """Test file names with various patterns""" @@ -461,10 +499,12 @@ def test_relative_run_script_with_odd_file_names(base_app, file_name, monkeypatc run_cmd(base_app, "_relative_run_script {}".format(utils.quote_string(file_name))) run_script_mock.assert_called_once_with(utils.quote_string(file_name)) + def test_relative_run_script_requires_an_argument(base_app): out, err = run_cmd(base_app, '_relative_run_script') assert 'Error: the following arguments' in err[1] + def test_in_script(request): class HookApp(cmd2.Cmd): def __init__(self, *args, **kwargs): @@ -483,17 +523,20 @@ def test_in_script(request): assert "WE ARE IN SCRIPT" in out[-1] + def test_system_exit_in_command(base_app, capsys): """Test raising SystemExit from a command""" import types def do_system_exit(self, _): raise SystemExit + setattr(base_app, 'do_system_exit', types.MethodType(do_system_exit, base_app)) stop = base_app.onecmd_plus_hooks('system_exit') assert stop + def test_output_redirection(base_app): fd, filename = tempfile.mkstemp(prefix='cmd2_test', suffix='.txt') os.close(fd) @@ -516,6 +559,7 @@ def test_output_redirection(base_app): finally: os.remove(filename) + def test_output_redirection_to_nonexistent_directory(base_app): filename = '~/fakedir/this_does_not_exist.txt' @@ -525,12 +569,15 @@ def test_output_redirection_to_nonexistent_directory(base_app): out, err = run_cmd(base_app, 'help >> {}'.format(filename)) assert 'Failed to redirect' in err[0] + def test_output_redirection_to_too_long_filename(base_app): - filename = '~/sdkfhksdjfhkjdshfkjsdhfkjsdhfkjdshfkjdshfkjshdfkhdsfkjhewfuihewiufhweiufhiweufhiuewhiuewhfiuwehfia' \ - 'ewhfiuewhfiuewhfiuewhiuewhfiuewhfiuewfhiuwehewiufhewiuhfiweuhfiuwehfiuewfhiuwehiuewfhiuewhiewuhfiueh' \ - 'fiuwefhewiuhewiufhewiufhewiufhewiufhewiufhewiufhewiufhewiuhewiufhewiufhewiuheiufhiuewheiwufhewiufheu' \ - 'fheiufhieuwhfewiuhfeiufhiuewfhiuewheiwuhfiuewhfiuewhfeiuwfhewiufhiuewhiuewhfeiuwhfiuwehfuiwehfiuehie' \ - 'whfieuwfhieufhiuewhfeiuwfhiuefhueiwhfw' + filename = ( + '~/sdkfhksdjfhkjdshfkjsdhfkjsdhfkjdshfkjdshfkjshdfkhdsfkjhewfuihewiufhweiufhiweufhiuewhiuewhfiuwehfia' + 'ewhfiuewhfiuewhfiuewhiuewhfiuewhfiuewfhiuwehewiufhewiuhfiweuhfiuwehfiuewfhiuwehiuewfhiuewhiewuhfiueh' + 'fiuwefhewiuhewiufhewiufhewiufhewiufhewiufhewiufhewiufhewiuhewiufhewiufhewiuheiufhiuewheiwufhewiufheu' + 'fheiufhieuwhfewiuhfeiufhiuewfhiuewheiwuhfiuewhfiuewhfeiuwfhewiufhiuewhiuewhfeiuwhfiuwehfuiwehfiuehie' + 'whfieuwfhieufhiuewhfeiuwfhiuefhueiwhfw' + ) out, err = run_cmd(base_app, 'help > {}'.format(filename)) assert 'Failed to redirect' in err[0] @@ -588,6 +635,7 @@ def test_disallow_redirection(base_app): # Verify that no file got created assert not os.path.exists(filename) + def test_pipe_to_shell(base_app): if sys.platform == "win32": # Windows @@ -600,6 +648,7 @@ def test_pipe_to_shell(base_app): out, err = run_cmd(base_app, command) assert out and not err + def test_pipe_to_shell_and_redirect(base_app): filename = 'out.txt' if sys.platform == "win32": @@ -615,14 +664,15 @@ def test_pipe_to_shell_and_redirect(base_app): assert os.path.exists(filename) os.remove(filename) + def test_pipe_to_shell_error(base_app): # Try to pipe command output to a shell command that doesn't exist in order to produce an error out, err = run_cmd(base_app, 'help | foobarbaz.this_does_not_exist') assert not out assert "Pipe process exited with code" in err[0] -@pytest.mark.skipif(not clipboard.can_clip, - reason="Pyperclip could not find a copy/paste mechanism for your system") + +@pytest.mark.skipif(not clipboard.can_clip, reason="Pyperclip could not find a copy/paste mechanism for your system") def test_send_to_paste_buffer(base_app): # Test writing to the PasteBuffer/Clipboard run_cmd(base_app, 'help >') @@ -639,9 +689,11 @@ def test_send_to_paste_buffer(base_app): def test_base_timing(base_app): base_app.feedback_to_output = False out, err = run_cmd(base_app, 'set timing True') - expected = normalize("""timing - was: False + expected = normalize( + """timing - was: False now: True -""") +""" + ) assert out == expected if sys.platform == 'win32': @@ -656,13 +708,18 @@ def _expected_no_editor_error(): if hasattr(sys, "pypy_translation_info"): expected_exception = 'EnvironmentError' - expected_text = normalize(""" + expected_text = normalize( + """ EXCEPTION of type '{}' occurred with message: 'Please use 'set editor' to specify your text editing program of choice.' To enable full traceback, run the following command: 'set debug true' -""".format(expected_exception)) +""".format( + expected_exception + ) + ) return expected_text + def test_base_debug(base_app): # Purposely set the editor to None base_app.editor = None @@ -675,16 +732,19 @@ def test_base_debug(base_app): # Set debug true out, err = run_cmd(base_app, 'set debug True') - expected = normalize(""" + expected = normalize( + """ debug - was: False now: True -""") +""" + ) assert out == expected # Verify that we now see the exception traceback out, err = run_cmd(base_app, 'edit') assert err[0].startswith('Traceback (most recent call last):') + def test_debug_not_settable(base_app): # Set debug to False and make it unsettable base_app.debug = False @@ -696,10 +756,12 @@ def test_debug_not_settable(base_app): # Since debug is unsettable, the user will not be given the option to enable a full traceback assert err == ['Invalid syntax: No closing quotation'] + def test_remove_settable_keyerror(base_app): with pytest.raises(KeyError): base_app.remove_settable('fake') + def test_edit_file(base_app, request, monkeypatch): # Set a fake editor just to make sure we have one. We aren't really going to call it due to the mock base_app.editor = 'fooedit' @@ -716,6 +778,7 @@ def test_edit_file(base_app, request, monkeypatch): # We think we have an editor, so should expect a Popen call m.assert_called_once() + @pytest.mark.parametrize('file_name', odd_file_names) def test_edit_file_with_odd_file_names(base_app, file_name, monkeypatch): """Test editor and file names with various patterns""" @@ -728,6 +791,7 @@ def test_edit_file_with_odd_file_names(base_app, file_name, monkeypatch): run_cmd(base_app, "edit {}".format(utils.quote_string(file_name))) shell_mock.assert_called_once_with('"fooedit" {}'.format(utils.quote_string(file_name))) + def test_edit_file_with_spaces(base_app, request, monkeypatch): # Set a fake editor just to make sure we have one. We aren't really going to call it due to the mock base_app.editor = 'fooedit' @@ -744,6 +808,7 @@ def test_edit_file_with_spaces(base_app, request, monkeypatch): # We think we have an editor, so should expect a Popen call m.assert_called_once() + def test_edit_blank(base_app, monkeypatch): # Set a fake editor just to make sure we have one. We aren't really going to call it due to the mock base_app.editor = 'fooedit' @@ -830,8 +895,8 @@ def test_cmdloop_without_rawinput(): out = app.stdout.getvalue() assert out == expected -@pytest.mark.skipif(sys.platform.startswith('win'), - reason="stty sane only run on Linux/Mac") + +@pytest.mark.skipif(sys.platform.startswith('win'), reason="stty sane only run on Linux/Mac") def test_stty_sane(base_app, monkeypatch): """Make sure stty sane is run on Linux/Mac after each command if stdin is a terminal""" with mock.patch('sys.stdin.isatty', mock.MagicMock(name='isatty', return_value=True)): @@ -842,6 +907,7 @@ def test_stty_sane(base_app, monkeypatch): base_app.onecmd_plus_hooks('help') m.assert_called_once_with(['stty', 'sane']) + class HookFailureApp(cmd2.Cmd): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -853,11 +919,13 @@ class HookFailureApp(cmd2.Cmd): data.stop = True return data + @pytest.fixture def hook_failure(): app = HookFailureApp() return app + def test_precmd_hook_success(base_app): out = base_app.onecmd_plus_hooks('help') assert out is False @@ -875,12 +943,14 @@ class SayApp(cmd2.Cmd): def do_say(self, arg): self.poutput(arg) + @pytest.fixture def say_app(): app = SayApp(allow_cli_args=False) app.stdout = utils.StdSim(app.stdout) return app + def test_interrupt_quit(say_app): say_app.quit_on_sigint = True @@ -898,6 +968,7 @@ def test_interrupt_quit(say_app): out = say_app.stdout.getvalue() assert out == 'hello\n' + def test_interrupt_noquit(say_app): say_app.quit_on_sigint = False @@ -921,6 +992,7 @@ class ShellApp(cmd2.Cmd): super().__init__(*args, **kwargs) self.default_to_shell = True + def test_default_to_shell(base_app, monkeypatch): if sys.platform.startswith('win'): line = 'dir' @@ -934,14 +1006,17 @@ def test_default_to_shell(base_app, monkeypatch): assert out == [] assert m.called + def test_ansi_prompt_not_esacped(base_app): from cmd2.rl_utils import rl_make_safe_prompt + prompt = '(Cmd) ' assert rl_make_safe_prompt(prompt) == prompt def test_ansi_prompt_escaped(): from cmd2.rl_utils import rl_make_safe_prompt + app = cmd2.Cmd() color = 'cyan' prompt = 'InColor' @@ -963,6 +1038,7 @@ def test_ansi_prompt_escaped(): class HelpApp(cmd2.Cmd): """Class for testing custom help_* methods which override docstring help.""" + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -996,24 +1072,29 @@ def help_app(): app = HelpApp() return app + def test_custom_command_help(help_app): out, err = run_cmd(help_app, 'help squat') expected = normalize('This command does diddly squat...') assert out == expected + def test_custom_help_menu(help_app): out, err = run_cmd(help_app, 'help') verify_help_text(help_app, out) + def test_help_undocumented(help_app): out, err = run_cmd(help_app, 'help undoc') assert err[0].startswith("No help on undoc") + def test_help_overridden_method(help_app): out, err = run_cmd(help_app, 'help edit') expected = normalize('This overrides the edit command and does nothing.') assert out == expected + def test_help_multiline_docstring(help_app): out, err = run_cmd(help_app, 'help multiline_docstr') expected = normalize('This documentation\nis multiple lines\nand there are no\ntabs') @@ -1022,6 +1103,7 @@ def test_help_multiline_docstring(help_app): class HelpCategoriesApp(cmd2.Cmd): """Class for testing custom help_* methods which override docstring help.""" + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -1052,15 +1134,18 @@ class HelpCategoriesApp(cmd2.Cmd): def do_undoc(self, arg): pass + @pytest.fixture def helpcat_app(): app = HelpCategoriesApp() return app + def test_help_cat_base(helpcat_app): out, err = run_cmd(helpcat_app, 'help') verify_help_text(helpcat_app, out) + def test_help_cat_verbose(helpcat_app): out, err = run_cmd(helpcat_app, 'help --verbose') verify_help_text(helpcat_app, out) @@ -1085,8 +1170,9 @@ class SelectApp(cmd2.Cmd): def do_procrastinate(self, arg): """Waste time in your manner of choice.""" # Pass in a list of tuples for selections - leisure_activity = self.select([('Netflix and chill', 'Netflix'), ('YouTube', 'WebSurfing')], - 'How would you like to procrastinate? ') + leisure_activity = self.select( + [('Netflix and chill', 'Netflix'), ('YouTube', 'WebSurfing')], 'How would you like to procrastinate? ' + ) result = 'Have fun procrasinating with {}!\n'.format(leisure_activity) self.stdout.write(result) @@ -1097,11 +1183,13 @@ class SelectApp(cmd2.Cmd): result = 'Charm us with the {}...\n'.format(instrument) self.stdout.write(result) + @pytest.fixture def select_app(): app = SelectApp() return app + def test_select_options(select_app, monkeypatch): # Mock out the read_input call so we don't actually wait for a user's response on stdin read_input_mock = mock.MagicMock(name='read_input', return_value='2') @@ -1109,11 +1197,15 @@ def test_select_options(select_app, monkeypatch): food = 'bacon' out, err = run_cmd(select_app, "eat {}".format(food)) - expected = normalize(""" + expected = normalize( + """ 1. sweet 2. salty {} with salty sauce, yum! -""".format(food)) +""".format( + food + ) + ) # Make sure our mock was called with the expected arguments read_input_mock.assert_called_once_with('Sauce? ') @@ -1121,6 +1213,7 @@ def test_select_options(select_app, monkeypatch): # And verify the expected output to stdout assert out == expected + def test_select_invalid_option_too_big(select_app, monkeypatch): # Mock out the input call so we don't actually wait for a user's response on stdin read_input_mock = mock.MagicMock(name='read_input') @@ -1131,12 +1224,16 @@ def test_select_invalid_option_too_big(select_app, monkeypatch): food = 'fish' out, err = run_cmd(select_app, "eat {}".format(food)) - expected = normalize(""" + expected = normalize( + """ 1. sweet 2. salty '3' isn't a valid choice. Pick a number between 1 and 2: {} with sweet sauce, yum! -""".format(food)) +""".format( + food + ) + ) # Make sure our mock was called exactly twice with the expected arguments arg = 'Sauce? ' @@ -1147,6 +1244,7 @@ def test_select_invalid_option_too_big(select_app, monkeypatch): # And verify the expected output to stdout assert out == expected + def test_select_invalid_option_too_small(select_app, monkeypatch): # Mock out the input call so we don't actually wait for a user's response on stdin read_input_mock = mock.MagicMock(name='read_input') @@ -1157,12 +1255,16 @@ def test_select_invalid_option_too_small(select_app, monkeypatch): food = 'fish' out, err = run_cmd(select_app, "eat {}".format(food)) - expected = normalize(""" + expected = normalize( + """ 1. sweet 2. salty '0' isn't a valid choice. Pick a number between 1 and 2: {} with sweet sauce, yum! -""".format(food)) +""".format( + food + ) + ) # Make sure our mock was called exactly twice with the expected arguments arg = 'Sauce? ' @@ -1173,17 +1275,22 @@ def test_select_invalid_option_too_small(select_app, monkeypatch): # And verify the expected output to stdout assert out == expected + def test_select_list_of_strings(select_app, monkeypatch): # Mock out the input call so we don't actually wait for a user's response on stdin read_input_mock = mock.MagicMock(name='read_input', return_value='2') monkeypatch.setattr("cmd2.Cmd.read_input", read_input_mock) out, err = run_cmd(select_app, "study") - expected = normalize(""" + expected = normalize( + """ 1. math 2. science Good luck learning {}! -""".format('science')) +""".format( + 'science' + ) + ) # Make sure our mock was called with the expected arguments read_input_mock.assert_called_once_with('Subject? ') @@ -1191,17 +1298,22 @@ Good luck learning {}! # And verify the expected output to stdout assert out == expected + def test_select_list_of_tuples(select_app, monkeypatch): # Mock out the input call so we don't actually wait for a user's response on stdin read_input_mock = mock.MagicMock(name='read_input', return_value='2') monkeypatch.setattr("cmd2.Cmd.read_input", read_input_mock) out, err = run_cmd(select_app, "procrastinate") - expected = normalize(""" + expected = normalize( + """ 1. Netflix 2. WebSurfing Have fun procrasinating with {}! -""".format('YouTube')) +""".format( + 'YouTube' + ) + ) # Make sure our mock was called with the expected arguments read_input_mock.assert_called_once_with('How would you like to procrastinate? ') @@ -1216,11 +1328,15 @@ def test_select_uneven_list_of_tuples(select_app, monkeypatch): monkeypatch.setattr("cmd2.Cmd.read_input", read_input_mock) out, err = run_cmd(select_app, "play") - expected = normalize(""" + expected = normalize( + """ 1. Electric Guitar 2. Drums Charm us with the {}... -""".format('Drums')) +""".format( + 'Drums' + ) + ) # Make sure our mock was called with the expected arguments read_input_mock.assert_called_once_with('Instrument? ') @@ -1228,6 +1344,7 @@ Charm us with the {}... # And verify the expected output to stdout assert out == expected + def test_select_eof(select_app, monkeypatch): # Ctrl-D during select causes an EOFError that just reprompts the user read_input_mock = mock.MagicMock(name='read_input', side_effect=[EOFError, 2]) @@ -1242,6 +1359,7 @@ def test_select_eof(select_app, monkeypatch): read_input_mock.assert_has_calls(calls) assert read_input_mock.call_count == 2 + def test_select_ctrl_c(outsim_app, monkeypatch, capsys): # Ctrl-C during select prints ^C and raises a KeyboardInterrupt read_input_mock = mock.MagicMock(name='read_input', side_effect=KeyboardInterrupt) @@ -1253,9 +1371,11 @@ def test_select_ctrl_c(outsim_app, monkeypatch, capsys): out = outsim_app.stdout.getvalue() assert out.rstrip().endswith('^C') + class HelpNoDocstringApp(cmd2.Cmd): greet_parser = argparse.ArgumentParser() greet_parser.add_argument('-s', '--shout', action="store_true", help="N00B EMULATION MODE") + @cmd2.with_argparser(greet_parser, with_unknown_args=True) def do_greet(self, opts, arg): arg = ''.join(arg) @@ -1263,17 +1383,22 @@ class HelpNoDocstringApp(cmd2.Cmd): arg = arg.upper() self.stdout.write(arg + '\n') + def test_help_with_no_docstring(capsys): app = HelpNoDocstringApp() app.onecmd_plus_hooks('greet -h') out, err = capsys.readouterr() assert err == '' - assert out == """usage: greet [-h] [-s] + assert ( + out + == """usage: greet [-h] [-s] optional arguments: -h, --help show this help message and exit -s, --shout N00B EMULATION MODE """ + ) + class MultilineApp(cmd2.Cmd): def __init__(self, *args, **kwargs): @@ -1289,15 +1414,18 @@ class MultilineApp(cmd2.Cmd): arg = arg.upper() self.stdout.write(arg + '\n') + @pytest.fixture def multiline_app(): app = MultilineApp() return app + def test_multiline_complete_empty_statement_raises_exception(multiline_app): with pytest.raises(exceptions.EmptyStatement): multiline_app._complete_statement('') + def test_multiline_complete_statement_without_terminator(multiline_app): # Mock out the input call so we don't actually wait for a user's response # on stdin when it looks for more input @@ -1312,6 +1440,7 @@ def test_multiline_complete_statement_without_terminator(multiline_app): assert statement.command == command assert statement.multiline_command == command + def test_multiline_complete_statement_with_unclosed_quotes(multiline_app): # Mock out the input call so we don't actually wait for a user's response # on stdin when it looks for more input @@ -1325,6 +1454,7 @@ def test_multiline_complete_statement_with_unclosed_quotes(multiline_app): assert statement.multiline_command == 'orate' assert statement.terminator == ';' + def test_multiline_input_line_to_statement(multiline_app): # Verify _input_line_to_statement saves the fully entered input line for multiline commands @@ -1340,6 +1470,7 @@ def test_multiline_input_line_to_statement(multiline_app): assert statement.command == 'orate' assert statement.multiline_command == 'orate' + def test_clipboard_failure(base_app, capsys): # Force cmd2 clipboard to be disabled base_app._can_clip = False @@ -1369,11 +1500,13 @@ class CommandResultApp(cmd2.Cmd): def do_negative_no_data(self, arg): self.last_result = cmd2.CommandResult('', arg) + @pytest.fixture def commandresult_app(): app = CommandResultApp() return app + def test_commandresult_truthy(commandresult_app): arg = 'foo' run_cmd(commandresult_app, 'affirmative {}'.format(arg)) @@ -1384,6 +1517,7 @@ def test_commandresult_truthy(commandresult_app): assert commandresult_app.last_result assert commandresult_app.last_result == cmd2.CommandResult(arg) + def test_commandresult_falsy(commandresult_app): arg = 'bar' run_cmd(commandresult_app, 'negative {}'.format(arg)) @@ -1409,6 +1543,7 @@ def test_eof(base_app): # Only thing to verify is that it returns True assert base_app.do_eof('') + def test_echo(capsys): app = cmd2.Cmd() app.echo = True @@ -1419,6 +1554,7 @@ def test_echo(capsys): out, err = capsys.readouterr() assert out.startswith('{}{}\n'.format(app.prompt, commands[0]) + HELP_HISTORY.split()[0]) + def test_read_input_rawinput_true(capsys, monkeypatch): prompt_str = 'the_prompt' input_str = 'some input' @@ -1450,6 +1586,7 @@ def test_read_input_rawinput_true(capsys, monkeypatch): assert line == input_str assert not out + def test_read_input_rawinput_false(capsys, monkeypatch): prompt_str = 'the_prompt' input_str = 'some input' @@ -1502,6 +1639,7 @@ def test_read_input_rawinput_false(capsys, monkeypatch): assert line == 'eof' assert not out + def test_read_command_line_eof(base_app, monkeypatch): read_input_mock = mock.MagicMock(name='read_input', side_effect=EOFError) monkeypatch.setattr("cmd2.Cmd.read_input", read_input_mock) @@ -1509,6 +1647,7 @@ def test_read_command_line_eof(base_app, monkeypatch): line = base_app._read_command_line("Prompt> ") assert line == 'eof' + def test_poutput_string(outsim_app): msg = 'This is a test' outsim_app.poutput(msg) @@ -1516,6 +1655,7 @@ def test_poutput_string(outsim_app): expected = msg + '\n' assert out == expected + def test_poutput_zero(outsim_app): msg = 0 outsim_app.poutput(msg) @@ -1523,6 +1663,7 @@ def test_poutput_zero(outsim_app): expected = str(msg) + '\n' assert out == expected + def test_poutput_empty_string(outsim_app): msg = '' outsim_app.poutput(msg) @@ -1530,6 +1671,7 @@ def test_poutput_empty_string(outsim_app): expected = '\n' assert out == expected + def test_poutput_none(outsim_app): msg = None outsim_app.poutput(msg) @@ -1537,6 +1679,7 @@ def test_poutput_none(outsim_app): expected = 'None\n' assert out == expected + def test_poutput_ansi_always(outsim_app): msg = 'Hello World' ansi.allow_style = ansi.STYLE_ALWAYS @@ -1547,6 +1690,7 @@ def test_poutput_ansi_always(outsim_app): assert colored_msg != msg assert out == expected + def test_poutput_ansi_never(outsim_app): msg = 'Hello World' ansi.allow_style = ansi.STYLE_NEVER @@ -1571,6 +1715,7 @@ invalid_command_name = [ 'noembedded"quotes', ] + def test_get_alias_completion_items(base_app): run_cmd(base_app, 'alias create fake run_pyscript') run_cmd(base_app, 'alias create ls !ls -hal') @@ -1582,6 +1727,7 @@ def test_get_alias_completion_items(base_app): assert cur_res in base_app.aliases assert cur_res.description == base_app.aliases[cur_res] + def test_get_macro_completion_items(base_app): run_cmd(base_app, 'macro create foo !echo foo') run_cmd(base_app, 'macro create bar !echo bar') @@ -1593,17 +1739,20 @@ def test_get_macro_completion_items(base_app): assert cur_res in base_app.macros assert cur_res.description == base_app.macros[cur_res].value + def test_get_settable_completion_items(base_app): results = base_app._get_settable_completion_items() for cur_res in results: assert cur_res in base_app.settables assert cur_res.description == base_app.settables[cur_res].description + def test_alias_no_subcommand(base_app): out, err = run_cmd(base_app, 'alias') assert "Usage: alias [-h]" in err[0] assert "Error: the following arguments are required: SUBCOMMAND" in err[1] + def test_alias_create(base_app): # Create the alias out, err = run_cmd(base_app, 'alias create fake run_pyscript') @@ -1636,6 +1785,7 @@ def test_alias_create(base_app): out, err = run_cmd(base_app, 'alias list --with_silent fake') assert out == normalize('alias create --silent fake set') + def test_alias_create_with_quoted_tokens(base_app): """Demonstrate that quotes in alias value will be preserved""" create_command = 'alias create fake help ">" "out file.txt" ";"' @@ -1648,21 +1798,25 @@ def test_alias_create_with_quoted_tokens(base_app): out, err = run_cmd(base_app, 'alias list fake') assert out == normalize(create_command) + @pytest.mark.parametrize('alias_name', invalid_command_name) def test_alias_create_invalid_name(base_app, alias_name, capsys): out, err = run_cmd(base_app, 'alias create {} help'.format(alias_name)) assert "Invalid alias name" in err[0] + def test_alias_create_with_command_name(base_app): out, err = run_cmd(base_app, 'alias create help stuff') assert "Alias cannot have the same name as a command" in err[0] + def test_alias_create_with_macro_name(base_app): macro = "my_macro" run_cmd(base_app, 'macro create {} help'.format(macro)) out, err = run_cmd(base_app, 'alias create {} help'.format(macro)) assert "Alias cannot have the same name as a macro" in err[0] + def test_alias_that_resolves_into_comment(base_app): # Create the alias out, err = run_cmd(base_app, 'alias create fake ' + constants.COMMENT_CHAR + ' blah blah') @@ -1673,11 +1827,13 @@ def test_alias_that_resolves_into_comment(base_app): assert not out assert not err + def test_alias_list_invalid_alias(base_app): # Look up invalid alias out, err = run_cmd(base_app, 'alias list invalid') assert "Alias 'invalid' not found" in err[0] + def test_alias_delete(base_app): # Create an alias run_cmd(base_app, 'alias create fake run_pyscript') @@ -1686,18 +1842,22 @@ def test_alias_delete(base_app): out, err = run_cmd(base_app, 'alias delete fake') assert out == normalize("Alias 'fake' deleted") + def test_alias_delete_all(base_app): out, err = run_cmd(base_app, 'alias delete --all') assert out == normalize("All aliases deleted") + def test_alias_delete_non_existing(base_app): out, err = run_cmd(base_app, 'alias delete fake') assert "Alias 'fake' does not exist" in err[0] + def test_alias_delete_no_name(base_app): out, err = run_cmd(base_app, 'alias delete') assert "Either --all or alias name(s)" in err[0] + def test_multiple_aliases(base_app): alias1 = 'h1' alias2 = 'h2' @@ -1709,11 +1869,13 @@ def test_multiple_aliases(base_app): out, err = run_cmd(base_app, alias2) verify_help_text(base_app, out) + def test_macro_no_subcommand(base_app): out, err = run_cmd(base_app, 'macro') assert "Usage: macro [-h]" in err[0] assert "Error: the following arguments are required: SUBCOMMAND" in err[1] + def test_macro_create(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake run_pyscript') @@ -1746,6 +1908,7 @@ def test_macro_create(base_app): out, err = run_cmd(base_app, 'macro list --with_silent fake') assert out == normalize('macro create --silent fake set') + def test_macro_create_with_quoted_tokens(base_app): """Demonstrate that quotes in macro value will be preserved""" create_command = 'macro create fake help ">" "out file.txt" ";"' @@ -1758,21 +1921,25 @@ def test_macro_create_with_quoted_tokens(base_app): out, err = run_cmd(base_app, 'macro list fake') assert out == normalize(create_command) + @pytest.mark.parametrize('macro_name', invalid_command_name) def test_macro_create_invalid_name(base_app, macro_name): out, err = run_cmd(base_app, 'macro create {} help'.format(macro_name)) assert "Invalid macro name" in err[0] + def test_macro_create_with_command_name(base_app): out, err = run_cmd(base_app, 'macro create help stuff') assert "Macro cannot have the same name as a command" in err[0] + def test_macro_create_with_alias_name(base_app): macro = "my_macro" run_cmd(base_app, 'alias create {} help'.format(macro)) out, err = run_cmd(base_app, 'macro create {} help'.format(macro)) assert "Macro cannot have the same name as an alias" in err[0] + def test_macro_create_with_args(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake {1} {2}') @@ -1782,6 +1949,7 @@ def test_macro_create_with_args(base_app): out, err = run_cmd(base_app, 'fake help -v') verify_help_text(base_app, out) + def test_macro_create_with_escaped_args(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake help {{1}}') @@ -1791,6 +1959,7 @@ def test_macro_create_with_escaped_args(base_app): out, err = run_cmd(base_app, 'fake') assert err[0].startswith('No help on {1}') + def test_macro_usage_with_missing_args(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake help {1} {2}') @@ -1800,6 +1969,7 @@ def test_macro_usage_with_missing_args(base_app): out, err = run_cmd(base_app, 'fake arg1') assert "expects at least 2 argument(s)" in err[0] + def test_macro_usage_with_exta_args(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake help {1}') @@ -1809,16 +1979,19 @@ def test_macro_usage_with_exta_args(base_app): out, err = run_cmd(base_app, 'fake alias create') assert "Usage: alias create" in out[0] + def test_macro_create_with_missing_arg_nums(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake help {1} {3}') assert "Not all numbers between 1 and 3" in err[0] + def test_macro_create_with_invalid_arg_num(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake help {1} {-1} {0}') assert "Argument numbers must be greater than 0" in err[0] + def test_macro_create_with_unicode_numbered_arg(base_app): # Create the macro expecting 1 argument out, err = run_cmd(base_app, 'macro create fake help {\N{ARABIC-INDIC DIGIT ONE}}') @@ -1828,10 +2001,12 @@ def test_macro_create_with_unicode_numbered_arg(base_app): out, err = run_cmd(base_app, 'fake') assert "expects at least 1 argument(s)" in err[0] + def test_macro_create_with_missing_unicode_arg_nums(base_app): out, err = run_cmd(base_app, 'macro create fake help {1} {\N{ARABIC-INDIC DIGIT THREE}}') assert "Not all numbers between 1 and 3" in err[0] + def test_macro_that_resolves_into_comment(base_app): # Create the macro out, err = run_cmd(base_app, 'macro create fake {1} blah blah') @@ -1842,11 +2017,13 @@ def test_macro_that_resolves_into_comment(base_app): assert not out assert not err + def test_macro_list_invalid_macro(base_app): # Look up invalid macro out, err = run_cmd(base_app, 'macro list invalid') assert "Macro 'invalid' not found" in err[0] + def test_macro_delete(base_app): # Create an macro run_cmd(base_app, 'macro create fake run_pyscript') @@ -1855,18 +2032,22 @@ def test_macro_delete(base_app): out, err = run_cmd(base_app, 'macro delete fake') assert out == normalize("Macro 'fake' deleted") + def test_macro_delete_all(base_app): out, err = run_cmd(base_app, 'macro delete --all') assert out == normalize("All macros deleted") + def test_macro_delete_non_existing(base_app): out, err = run_cmd(base_app, 'macro delete fake') assert "Macro 'fake' does not exist" in err[0] + def test_macro_delete_no_name(base_app): out, err = run_cmd(base_app, 'macro delete') assert "Either --all or macro name(s)" in err[0] + def test_multiple_macros(base_app): macro1 = 'h1' macro2 = 'h2' @@ -1879,8 +2060,10 @@ def test_multiple_macros(base_app): verify_help_text(base_app, out2) assert len(out2) > len(out) + def test_nonexistent_macro(base_app): from cmd2.parsing import StatementParser + exception = None try: @@ -1890,6 +2073,7 @@ def test_nonexistent_macro(base_app): assert exception is not None + def test_perror_style(base_app, capsys): msg = 'testing...' end = '\n' @@ -1898,6 +2082,7 @@ def test_perror_style(base_app, capsys): out, err = capsys.readouterr() assert err == ansi.style_error(msg) + end + def test_perror_no_style(base_app, capsys): msg = 'testing...' end = '\n' @@ -1906,6 +2091,7 @@ def test_perror_no_style(base_app, capsys): out, err = capsys.readouterr() assert err == msg + end + def test_pwarning_style(base_app, capsys): msg = 'testing...' end = '\n' @@ -1914,6 +2100,7 @@ def test_pwarning_style(base_app, capsys): out, err = capsys.readouterr() assert err == ansi.style_warning(msg) + end + def test_pwarning_no_style(base_app, capsys): msg = 'testing...' end = '\n' @@ -1922,6 +2109,7 @@ def test_pwarning_no_style(base_app, capsys): out, err = capsys.readouterr() assert err == msg + end + def test_ppaged(outsim_app): msg = 'testing...' end = '\n' @@ -1929,18 +2117,21 @@ def test_ppaged(outsim_app): out = outsim_app.stdout.getvalue() assert out == msg + end + def test_ppaged_blank(outsim_app): msg = '' outsim_app.ppaged(msg) out = outsim_app.stdout.getvalue() assert not out + def test_ppaged_none(outsim_app): msg = None outsim_app.ppaged(msg) out = outsim_app.stdout.getvalue() assert not out + def test_ppaged_strips_ansi_when_redirecting(outsim_app): msg = 'testing...' end = '\n' @@ -1950,6 +2141,7 @@ def test_ppaged_strips_ansi_when_redirecting(outsim_app): out = outsim_app.stdout.getvalue() assert out == msg + end + def test_ppaged_strips_ansi_when_redirecting_if_always(outsim_app): msg = 'testing...' end = '\n' @@ -1960,6 +2152,7 @@ def test_ppaged_strips_ansi_when_redirecting_if_always(outsim_app): out = outsim_app.stdout.getvalue() assert out == colored_msg + end + # we override cmd.parseline() so we always get consistent # command parsing by parent methods we don't override # don't need to test all the parsing logic here, because @@ -1971,6 +2164,7 @@ def test_parseline_empty(base_app): assert not args assert not line + def test_parseline(base_app): statement = " command with 'partially completed quotes " command, args, line = base_app.parseline(statement) @@ -1986,6 +2180,7 @@ def test_onecmd_raw_str_continue(outsim_app): assert not stop verify_help_text(outsim_app, out) + def test_onecmd_raw_str_quit(outsim_app): line = "quit" stop = outsim_app.onecmd(line) @@ -1993,6 +2188,7 @@ def test_onecmd_raw_str_quit(outsim_app): assert stop assert out == '' + def test_onecmd_add_to_history(outsim_app): line = "help" saved_hist_len = len(outsim_app.history) @@ -2009,18 +2205,35 @@ def test_onecmd_add_to_history(outsim_app): new_hist_len = len(outsim_app.history) assert new_hist_len == saved_hist_len + def test_get_all_commands(base_app): # Verify that the base app has the expected commands commands = base_app.get_all_commands() - expected_commands = ['_relative_run_script', 'alias', 'edit', 'eof', 'help', 'history', 'macro', - 'py', 'quit', 'run_pyscript', 'run_script', 'set', 'shell', 'shortcuts'] + expected_commands = [ + '_relative_run_script', + 'alias', + 'edit', + 'eof', + 'help', + 'history', + 'macro', + 'py', + 'quit', + 'run_pyscript', + 'run_script', + 'set', + 'shell', + 'shortcuts', + ] assert commands == expected_commands + def test_get_help_topics(base_app): # Verify that the base app has no additional help_foo methods custom_help = base_app.get_help_topics() assert len(custom_help) == 0 + def test_get_help_topics_hidden(): # Verify get_help_topics() filters out hidden commands class TestApp(cmd2.Cmd): @@ -2039,6 +2252,7 @@ def test_get_help_topics_hidden(): app.hidden_commands.append('my_cmd') assert 'my_cmd' not in app.get_help_topics() + class ReplWithExitCode(cmd2.Cmd): """ Example cmd2 application where we can specify an exit code when existing.""" @@ -2068,12 +2282,14 @@ Usage: exit [exit_code] """Hook method executed once when the cmdloop() method is about to return.""" self.poutput('exiting with code: {}'.format(self.exit_code)) + @pytest.fixture def exit_code_repl(): app = ReplWithExitCode() app.stdout = utils.StdSim(app.stdout) return app + def test_exit_code_default(exit_code_repl): app = exit_code_repl app.use_rawinput = True @@ -2089,6 +2305,7 @@ def test_exit_code_default(exit_code_repl): out = app.stdout.getvalue() assert out == expected + def test_exit_code_nonzero(exit_code_repl): app = exit_code_repl app.use_rawinput = True @@ -2118,6 +2335,7 @@ class AnsiApp(cmd2.Cmd): # perror uses colors by default self.perror(args) + def test_ansi_pouterr_always_tty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_ALWAYS @@ -2140,6 +2358,7 @@ def test_ansi_pouterr_always_tty(mocker, capsys): assert len(err) > len('oopsie\n') assert 'oopsie' in err + def test_ansi_pouterr_always_notty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_ALWAYS @@ -2162,6 +2381,7 @@ def test_ansi_pouterr_always_notty(mocker, capsys): assert len(err) > len('oopsie\n') assert 'oopsie' in err + def test_ansi_terminal_tty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_TERMINAL @@ -2183,6 +2403,7 @@ def test_ansi_terminal_tty(mocker, capsys): assert len(err) > len('oopsie\n') assert 'oopsie' in err + def test_ansi_terminal_notty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_TERMINAL @@ -2197,6 +2418,7 @@ def test_ansi_terminal_notty(mocker, capsys): out, err = capsys.readouterr() assert out == err == 'oopsie\n' + def test_ansi_never_tty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_NEVER @@ -2211,6 +2433,7 @@ def test_ansi_never_tty(mocker, capsys): out, err = capsys.readouterr() assert out == err == 'oopsie\n' + def test_ansi_never_notty(mocker, capsys): app = AnsiApp() ansi.allow_style = ansi.STYLE_NEVER @@ -2228,6 +2451,7 @@ def test_ansi_never_notty(mocker, capsys): class DisableCommandsApp(cmd2.Cmd): """Class for disabling commands""" + category_name = "Test Category" def __init__(self, *args, **kwargs): @@ -2346,6 +2570,7 @@ def test_disable_and_enable_category(disable_commands_app): help_topics = disable_commands_app.get_help_topics() assert 'has_helper_funcs' in help_topics + def test_enable_enabled_command(disable_commands_app): # Test enabling a command that is not disabled saved_len = len(disable_commands_app.disabled_commands) @@ -2354,10 +2579,12 @@ def test_enable_enabled_command(disable_commands_app): # The number of disabled_commands should not have changed assert saved_len == len(disable_commands_app.disabled_commands) + def test_disable_fake_command(disable_commands_app): with pytest.raises(AttributeError): disable_commands_app.disable_command('fake', 'fake message') + def test_disable_command_twice(disable_commands_app): saved_len = len(disable_commands_app.disabled_commands) message_to_print = 'These commands are currently disabled' @@ -2373,6 +2600,7 @@ def test_disable_command_twice(disable_commands_app): new_len = len(disable_commands_app.disabled_commands) assert saved_len == new_len + def test_disabled_command_not_in_history(disable_commands_app): message_to_print = 'These commands are currently disabled' disable_commands_app.disable_command('has_helper_funcs', message_to_print) @@ -2381,6 +2609,7 @@ def test_disabled_command_not_in_history(disable_commands_app): run_cmd(disable_commands_app, 'has_helper_funcs') assert saved_len == len(disable_commands_app.history) + def test_disabled_message_command_name(disable_commands_app): message_to_print = '{} is currently disabled'.format(COMMAND_NAME) disable_commands_app.disable_command('has_helper_funcs', message_to_print) |