diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/conftest.py | 13 | ||||
-rw-r--r-- | tests/scripts/postcmds.txt | 2 | ||||
-rw-r--r-- | tests/scripts/precmds.txt | 2 | ||||
-rw-r--r-- | tests/test_ansi.py | 25 | ||||
-rw-r--r-- | tests/test_argparse_completer.py | 4 | ||||
-rwxr-xr-x | tests/test_cmd2.py | 139 | ||||
-rwxr-xr-x | tests/test_history.py | 28 | ||||
-rw-r--r-- | tests/test_run_pyscript.py | 27 | ||||
-rw-r--r-- | tests/test_utils.py | 198 | ||||
-rw-r--r-- | tests/transcripts/regex_set.txt | 2 |
10 files changed, 297 insertions, 143 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index e09e07b1..fe74ffe2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -88,7 +88,7 @@ SHORTCUTS_TXT = """Shortcuts for other commands: """ # Output from the show command with default settings -SHOW_TXT = """allow_ansi: Terminal +SHOW_TXT = """allow_style: Terminal continuation_prompt: > debug: False echo: False @@ -102,7 +102,7 @@ timing: False """ SHOW_LONG = """ -allow_ansi: Terminal # Allow ANSI escape sequences in output (valid values: Terminal, Always, Never) +allow_style: Terminal # Allow ANSI text style sequences in output (valid values: Terminal, Always, Never) continuation_prompt: > # On 2nd+ line of input debug: False # Show full error stack on error echo: False # Echo command issued into output @@ -157,6 +157,15 @@ def base_app(): return cmd2.Cmd() +# These are odd file names for testing quoting of them +odd_file_names = [ + 'nothingweird', + 'has spaces', + '"is_double_quoted"', + "'is_single_quoted'" +] + + def complete_tester(text: str, line: str, begidx: int, endidx: int, app) -> Optional[str]: """ This is a convenience function to test cmd2.complete() since diff --git a/tests/scripts/postcmds.txt b/tests/scripts/postcmds.txt index 74f1e226..30f47055 100644 --- a/tests/scripts/postcmds.txt +++ b/tests/scripts/postcmds.txt @@ -1 +1 @@ -set allow_ansi Never +set allow_style Never diff --git a/tests/scripts/precmds.txt b/tests/scripts/precmds.txt index 0167aa22..7d036acf 100644 --- a/tests/scripts/precmds.txt +++ b/tests/scripts/precmds.txt @@ -1 +1 @@ -set allow_ansi Always +set allow_style Always diff --git a/tests/test_ansi.py b/tests/test_ansi.py index 056bb2db..cb68cb28 100644 --- a/tests/test_ansi.py +++ b/tests/test_ansi.py @@ -10,17 +10,17 @@ import cmd2.ansi as ansi HELLO_WORLD = 'Hello, world!' -def test_strip_ansi(): +def test_strip_style(): base_str = HELLO_WORLD ansi_str = ansi.style(base_str, fg='green') assert base_str != ansi_str - assert base_str == ansi.strip_ansi(ansi_str) + assert base_str == ansi.strip_style(ansi_str) -def test_ansi_safe_wcswidth(): +def test_style_aware_wcswidth(): base_str = HELLO_WORLD ansi_str = ansi.style(base_str, fg='green') - assert ansi.ansi_safe_wcswidth(ansi_str) != len(ansi_str) + assert ansi.style_aware_wcswidth(ansi_str) != len(ansi_str) def test_style_none(): @@ -45,10 +45,16 @@ def test_style_bg(): def test_style_bold(): base_str = HELLO_WORLD - ansi_str = ansi.BRIGHT + base_str + ansi.NORMAL + ansi_str = ansi.INTENSITY_BRIGHT + base_str + ansi.INTENSITY_NORMAL assert ansi.style(base_str, bold=True) == ansi_str +def test_style_dim(): + base_str = HELLO_WORLD + ansi_str = ansi.INTENSITY_DIM + base_str + ansi.INTENSITY_NORMAL + assert ansi.style(base_str, dim=True) == ansi_str + + def test_style_underline(): base_str = HELLO_WORLD ansi_str = ansi.UNDERLINE_ENABLE + base_str + ansi.UNDERLINE_DISABLE @@ -59,9 +65,12 @@ def test_style_multi(): base_str = HELLO_WORLD fg_color = 'blue' bg_color = 'green' - ansi_str = ansi.FG_COLORS[fg_color] + ansi.BG_COLORS[bg_color] + ansi.BRIGHT + ansi.UNDERLINE_ENABLE + \ - base_str + ansi.FG_RESET + ansi.BG_RESET + ansi.NORMAL + ansi.UNDERLINE_DISABLE - assert ansi.style(base_str, fg=fg_color, bg=bg_color, bold=True, underline=True) == ansi_str + ansi_str = (ansi.FG_COLORS[fg_color] + ansi.BG_COLORS[bg_color] + + ansi.INTENSITY_BRIGHT + ansi.INTENSITY_DIM + ansi.UNDERLINE_ENABLE + + base_str + + ansi.FG_RESET + ansi.BG_RESET + + ansi.INTENSITY_NORMAL + ansi.INTENSITY_NORMAL + ansi.UNDERLINE_DISABLE) + assert ansi.style(base_str, fg=fg_color, bg=bg_color, bold=True, dim=True, underline=True) == ansi_str def test_style_color_not_exist(): diff --git a/tests/test_argparse_completer.py b/tests/test_argparse_completer.py index b904a6ac..97c75ef3 100644 --- a/tests/test_argparse_completer.py +++ b/tests/test_argparse_completer.py @@ -535,11 +535,11 @@ def test_autocomp_blank_token(ac_app): def test_completion_items(ac_app, num_aliases, show_description): # Create aliases for i in range(0, num_aliases): - run_cmd(ac_app, 'alias create fake{} help'.format(i)) + run_cmd(ac_app, 'alias create fake_alias{} help'.format(i)) assert len(ac_app.aliases) == num_aliases - text = 'fake' + text = 'fake_alias' line = 'alias list {}'.format(text) endidx = len(line) begidx = endidx - len(text) diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 88447416..b5473609 100755 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -21,8 +21,8 @@ except ImportError: import cmd2 from cmd2 import ansi, clipboard, constants, plugin, utils, COMMAND_NAME -from .conftest import run_cmd, normalize, verify_help_text, HELP_HISTORY -from .conftest import SHORTCUTS_TXT, SHOW_TXT, SHOW_LONG, complete_tester +from .conftest import (run_cmd, normalize, verify_help_text, HELP_HISTORY, SHORTCUTS_TXT, SHOW_TXT, + SHOW_LONG, complete_tester, odd_file_names) def CreateOutsimApp(): c = cmd2.Cmd() @@ -187,26 +187,26 @@ now: True assert out == ['quiet: True'] @pytest.mark.parametrize('new_val, is_valid, expected', [ - (ansi.ANSI_NEVER, False, ansi.ANSI_NEVER), - ('neVeR', False, ansi.ANSI_NEVER), - (ansi.ANSI_TERMINAL, False, ansi.ANSI_TERMINAL), - ('TeRMInal', False, ansi.ANSI_TERMINAL), - (ansi.ANSI_ALWAYS, False, ansi.ANSI_ALWAYS), - ('AlWaYs', False, ansi.ANSI_ALWAYS), - ('invalid', True, ansi.ANSI_TERMINAL), + (ansi.STYLE_NEVER, False, ansi.STYLE_NEVER), + ('neVeR', False, ansi.STYLE_NEVER), + (ansi.STYLE_TERMINAL, False, ansi.STYLE_TERMINAL), + ('TeRMInal', False, ansi.STYLE_TERMINAL), + (ansi.STYLE_ALWAYS, False, ansi.STYLE_ALWAYS), + ('AlWaYs', False, ansi.STYLE_ALWAYS), + ('invalid', True, ansi.STYLE_TERMINAL), ]) -def test_set_allow_ansi(base_app, new_val, is_valid, expected): - # Initialize allow_ansi for this test - ansi.allow_ansi = ansi.ANSI_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 # Use the set command to alter it - out, err = run_cmd(base_app, 'set allow_ansi {}'.format(new_val)) + out, err = run_cmd(base_app, 'set allow_style {}'.format(new_val)) # Verify the results assert bool(err) == is_valid - assert ansi.allow_ansi == expected + assert ansi.allow_style == expected - # Reload ansi module to reset allow_ansi to its default since it's an + # Reload ansi module to reset allow_style to its default since it's an # application-wide setting that can affect other unit tests. import importlib importlib.reload(ansi) @@ -376,11 +376,11 @@ def test_run_script_nested_run_scripts(base_app, request): expected = """ %s _relative_run_script precmds.txt -set allow_ansi Always +set allow_style Always help shortcuts _relative_run_script postcmds.txt -set allow_ansi Never""" % initial_run +set allow_style Never""" % initial_run out, err = run_cmd(base_app, 'history -s') assert out == normalize(expected) @@ -395,11 +395,11 @@ def test_runcmds_plus_hooks(base_app, request): 'run_script ' + postfilepath]) expected = """ run_script %s -set allow_ansi Always +set allow_style Always help shortcuts run_script %s -set allow_ansi Never""" % (prefilepath, postfilepath) +set allow_style Never""" % (prefilepath, postfilepath) out, err = run_cmd(base_app, 'history -s') assert out == normalize(expected) @@ -431,31 +431,15 @@ def test_relative_run_script(base_app, request): assert script_out == manual_out assert script_err == manual_err -def test_relative_run_script_with_odd_file_names(base_app, monkeypatch): +@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""" # Mock out the do_run_script call to see what args are passed to it run_script_mock = mock.MagicMock(name='do_run_script') monkeypatch.setattr("cmd2.Cmd.do_run_script", run_script_mock) - file_name = utils.quote_string('nothingweird.txt') - out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name)) - run_script_mock.assert_called_once_with('"nothingweird.txt"') - run_script_mock.reset_mock() - - file_name = utils.quote_string('has spaces.txt') - out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name)) - run_script_mock.assert_called_once_with('"has spaces.txt"') - run_script_mock.reset_mock() - - file_name = utils.quote_string('"is_double_quoted.txt"') - out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name)) - run_script_mock.assert_called_once_with('\'"is_double_quoted.txt"\'') - run_script_mock.reset_mock() - - file_name = utils.quote_string("'is_single_quoted.txt'") - out, err = run_cmd(base_app, "_relative_run_script {}".format(file_name)) - run_script_mock.assert_called_once_with('"\'is_single_quoted.txt\'"') - run_script_mock.reset_mock() + 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') @@ -715,7 +699,8 @@ def test_edit_file(base_app, request, monkeypatch): # We think we have an editor, so should expect a Popen call m.assert_called_once() -def test_edit_file_with_odd_file_names(base_app, monkeypatch): +@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""" # Mock out the do_shell call to see what args are passed to it shell_mock = mock.MagicMock(name='do_shell') @@ -723,27 +708,8 @@ def test_edit_file_with_odd_file_names(base_app, monkeypatch): base_app.editor = 'fooedit' file_name = utils.quote_string('nothingweird.py') - out, err = run_cmd(base_app, "edit {}".format(file_name)) - shell_mock.assert_called_once_with('"fooedit" "nothingweird.py"') - shell_mock.reset_mock() - - base_app.editor = 'foo edit' - file_name = utils.quote_string('has spaces.py') - out, err = run_cmd(base_app, "edit {}".format(file_name)) - shell_mock.assert_called_once_with('"foo edit" "has spaces.py"') - shell_mock.reset_mock() - - base_app.editor = '"fooedit"' - file_name = utils.quote_string('"is_double_quoted.py"') - out, err = run_cmd(base_app, "edit {}".format(file_name)) - shell_mock.assert_called_once_with('\'"fooedit"\' \'"is_double_quoted.py"\'') - shell_mock.reset_mock() - - base_app.editor = "'fooedit'" - file_name = utils.quote_string("'is_single_quoted.py'") - out, err = run_cmd(base_app, "edit {}".format(file_name)) - shell_mock.assert_called_once_with('"\'fooedit\'" "\'is_single_quoted.py\'"') - shell_mock.reset_mock() + 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 @@ -1564,7 +1530,7 @@ def test_poutput_none(outsim_app): def test_poutput_ansi_always(outsim_app): msg = 'Hello World' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS colored_msg = ansi.style(msg, fg='cyan') outsim_app.poutput(colored_msg) out = outsim_app.stdout.getvalue() @@ -1574,7 +1540,7 @@ def test_poutput_ansi_always(outsim_app): def test_poutput_ansi_never(outsim_app): msg = 'Hello World' - ansi.allow_ansi = ansi.ANSI_NEVER + ansi.allow_style = ansi.STYLE_NEVER colored_msg = ansi.style(msg, fg='cyan') outsim_app.poutput(colored_msg) out = outsim_app.stdout.getvalue() @@ -1885,7 +1851,7 @@ def test_nonexistent_macro(base_app): def test_perror_style(base_app, capsys): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS base_app.perror(msg) out, err = capsys.readouterr() assert err == ansi.style_error(msg) + end @@ -1893,7 +1859,7 @@ def test_perror_style(base_app, capsys): def test_perror_no_style(base_app, capsys): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS base_app.perror(msg, apply_style=False) out, err = capsys.readouterr() assert err == msg + end @@ -1901,7 +1867,7 @@ def test_perror_no_style(base_app, capsys): def test_pwarning_style(base_app, capsys): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS base_app.pwarning(msg) out, err = capsys.readouterr() assert err == ansi.style_warning(msg) + end @@ -1909,7 +1875,7 @@ def test_pwarning_style(base_app, capsys): def test_pwarning_no_style(base_app, capsys): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS base_app.pwarning(msg, apply_style=False) out, err = capsys.readouterr() assert err == msg + end @@ -1936,7 +1902,7 @@ def test_ppaged_none(outsim_app): def test_ppaged_strips_ansi_when_redirecting(outsim_app): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_TERMINAL + ansi.allow_style = ansi.STYLE_TERMINAL outsim_app._redirecting = True outsim_app.ppaged(ansi.style(msg, fg='red')) out = outsim_app.stdout.getvalue() @@ -1945,7 +1911,7 @@ def test_ppaged_strips_ansi_when_redirecting(outsim_app): def test_ppaged_strips_ansi_when_redirecting_if_always(outsim_app): msg = 'testing...' end = '\n' - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS outsim_app._redirecting = True colored_msg = ansi.style(msg, fg='red') outsim_app.ppaged(colored_msg) @@ -2112,13 +2078,13 @@ class AnsiApp(cmd2.Cmd): def test_ansi_pouterr_always_tty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS mocker.patch.object(app.stdout, 'isatty', return_value=True) mocker.patch.object(sys.stderr, 'isatty', return_value=True) app.onecmd_plus_hooks('echo_error oopsie') out, err = capsys.readouterr() - # if colors are on, the output should have some escape sequences in it + # if colors are on, the output should have some ANSI style sequences in it assert len(out) > len('oopsie\n') assert 'oopsie' in out assert len(err) > len('oopsie\n') @@ -2134,13 +2100,13 @@ def test_ansi_pouterr_always_tty(mocker, capsys): def test_ansi_pouterr_always_notty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_ALWAYS + ansi.allow_style = ansi.STYLE_ALWAYS mocker.patch.object(app.stdout, 'isatty', return_value=False) mocker.patch.object(sys.stderr, 'isatty', return_value=False) app.onecmd_plus_hooks('echo_error oopsie') out, err = capsys.readouterr() - # if colors are on, the output should have some escape sequences in it + # if colors are on, the output should have some ANSI style sequences in it assert len(out) > len('oopsie\n') assert 'oopsie' in out assert len(err) > len('oopsie\n') @@ -2156,12 +2122,12 @@ def test_ansi_pouterr_always_notty(mocker, capsys): def test_ansi_terminal_tty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_TERMINAL + ansi.allow_style = ansi.STYLE_TERMINAL mocker.patch.object(app.stdout, 'isatty', return_value=True) mocker.patch.object(sys.stderr, 'isatty', return_value=True) app.onecmd_plus_hooks('echo_error oopsie') - # if colors are on, the output should have some escape sequences in it + # if colors are on, the output should have some ANSI style sequences in it out, err = capsys.readouterr() assert len(out) > len('oopsie\n') assert 'oopsie' in out @@ -2177,7 +2143,7 @@ def test_ansi_terminal_tty(mocker, capsys): def test_ansi_terminal_notty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_TERMINAL + ansi.allow_style = ansi.STYLE_TERMINAL mocker.patch.object(app.stdout, 'isatty', return_value=False) mocker.patch.object(sys.stderr, 'isatty', return_value=False) @@ -2191,7 +2157,7 @@ def test_ansi_terminal_notty(mocker, capsys): def test_ansi_never_tty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_NEVER + ansi.allow_style = ansi.STYLE_NEVER mocker.patch.object(app.stdout, 'isatty', return_value=True) mocker.patch.object(sys.stderr, 'isatty', return_value=True) @@ -2205,7 +2171,7 @@ def test_ansi_never_tty(mocker, capsys): def test_ansi_never_notty(mocker, capsys): app = AnsiApp() - ansi.allow_ansi = ansi.ANSI_NEVER + ansi.allow_style = ansi.STYLE_NEVER mocker.patch.object(app.stdout, 'isatty', return_value=False) mocker.patch.object(sys.stderr, 'isatty', return_value=False) @@ -2386,7 +2352,7 @@ def test_startup_script(request): startup_script = os.path.join(test_dir, '.cmd2rc') app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script) assert len(app._startup_commands) == 1 - assert app._startup_commands[0] == "run_script '{}'".format(startup_script) + assert app._startup_commands[0] == "run_script {}".format(utils.quote_string(startup_script)) app._startup_commands.append('quit') app.cmdloop() out, err = run_cmd(app, 'alias list') @@ -2394,6 +2360,21 @@ def test_startup_script(request): assert 'alias create ls' in out[0] +@pytest.mark.parametrize('startup_script', odd_file_names) +def test_startup_script_with_odd_file_names(startup_script): + """Test file names with various patterns""" + # Mock os.path.exists to trick cmd2 into adding this script to its startup commands + saved_exists = os.path.exists + os.path.exists = mock.MagicMock(name='exists', return_value=True) + + app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script) + assert len(app._startup_commands) == 1 + assert app._startup_commands[0] == "run_script {}".format(utils.quote_string(os.path.abspath(startup_script))) + + # Restore os.path.exists + os.path.exists = saved_exists + + def test_transcripts_at_init(): transcript_files = ['foo', 'bar'] app = cmd2.Cmd(allow_cli_args=False, transcript_files=transcript_files) diff --git a/tests/test_history.py b/tests/test_history.py index 4b900030..11f189f6 100755 --- a/tests/test_history.py +++ b/tests/test_history.py @@ -447,15 +447,17 @@ def test_history_with_span_index_error(base_app): with pytest.raises(ValueError): base_app.onecmd('history "hal :"') -def test_history_output_file(base_app): - run_cmd(base_app, 'help') - run_cmd(base_app, 'shortcuts') - run_cmd(base_app, 'help history') +def test_history_output_file(): + app = cmd2.Cmd(multiline_commands=['alias']) + run_cmd(app, 'help') + run_cmd(app, 'shortcuts') + run_cmd(app, 'help history') + run_cmd(app, 'alias create my_alias history;') fd, fname = tempfile.mkstemp(prefix='', suffix='.txt') os.close(fd) - run_cmd(base_app, 'history -o "{}"'.format(fname)) - expected = normalize('\n'.join(['help', 'shortcuts', 'help history'])) + run_cmd(app, 'history -o "{}"'.format(fname)) + expected = normalize('\n'.join(['help', 'shortcuts', 'help history', 'alias create my_alias history;'])) with open(fname) as f: content = normalize(f.read()) assert content == expected @@ -471,10 +473,12 @@ def test_history_bad_output_file(base_app): assert not out assert "Error saving" in err[0] -def test_history_edit(base_app, monkeypatch): +def test_history_edit(monkeypatch): + app = cmd2.Cmd(multiline_commands=['alias']) + # 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' + app.editor = 'fooedit' # Mock out the _run_editor call so we don't actually open an editor edit_mock = mock.MagicMock(name='_run_editor') @@ -484,9 +488,11 @@ def test_history_edit(base_app, monkeypatch): run_script_mock = mock.MagicMock(name='do_run_script') monkeypatch.setattr("cmd2.Cmd.do_run_script", run_script_mock) - # Run help command just so we have a command in history - run_cmd(base_app, 'help') - run_cmd(base_app, 'history -e 1') + # Put commands in history + run_cmd(app, 'help') + run_cmd(app, 'alias create my_alias history;') + + run_cmd(app, 'history -e 1:2') # Make sure both functions were called edit_mock.assert_called_once() diff --git a/tests/test_run_pyscript.py b/tests/test_run_pyscript.py index a4ff097f..d717758c 100644 --- a/tests/test_run_pyscript.py +++ b/tests/test_run_pyscript.py @@ -6,8 +6,10 @@ Unit/functional testing for run_pytest in cmd2 import builtins import os +import pytest + from cmd2 import plugin, utils -from .conftest import run_cmd +from .conftest import run_cmd, odd_file_names # Python 3.5 had some regressions in the unitest.mock module, so use 3rd party mock if available try: @@ -52,30 +54,19 @@ def test_run_pyscript_with_non_python_file(base_app, request): out, err = run_cmd(base_app, 'run_pyscript {}'.format(filename)) assert "does not have a .py extension" in err[0] -def test_run_pyscript_with_odd_file_names(base_app): +@pytest.mark.parametrize('python_script', odd_file_names) +def test_run_pyscript_with_odd_file_names(base_app, python_script): """ Pass in file names with various patterns. Since these files don't exist, we will rely on the error text to make sure the file names were processed correctly. """ - python_script = utils.quote_string('nothingweird.py') - out, err = run_cmd(base_app, "run_pyscript {}".format(python_script)) - assert "Error reading script file 'nothingweird.py'" in err[0] - - python_script = utils.quote_string('has spaces.py') - out, err = run_cmd(base_app, "run_pyscript {}".format(python_script)) - assert "Error reading script file 'has spaces.py'" in err[0] - - # For remaining tests, mock input to get us passed the warning about not ending in .py + # Mock input to get us passed the warning about not ending in .py input_mock = mock.MagicMock(name='input', return_value='1') builtins.input = input_mock - python_script = utils.quote_string('"is_double_quoted.py"') - out, err = run_cmd(base_app, "run_pyscript {}".format(python_script)) - assert "Error reading script file '\"is_double_quoted.py\"'" in err[1] - - python_script = utils.quote_string("'is_single_quoted.py'") - out, err = run_cmd(base_app, "run_pyscript {}".format(python_script)) - assert "Error reading script file ''is_single_quoted.py''" in err[1] + out, err = run_cmd(base_app, "run_pyscript {}".format(utils.quote_string(python_script))) + err = ''.join(err) + assert "Error reading script file '{}'".format(python_script) in err def test_run_pyscript_with_exception(base_app, request): test_dir = os.path.dirname(request.module.__file__) diff --git a/tests/test_utils.py b/tests/test_utils.py index e4b9169c..b5231172 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -293,24 +293,182 @@ def test_context_flag_exit_err(context_flag): context_flag.__exit__() -def test_center_text_pad_none(): - msg = 'foo' - centered = cu.center_text(msg, pad=None) - expected_center = ' ' + msg + ' ' - assert expected_center in centered - letters_in_centered = set(centered) - letters_in_msg = set(msg) - assert len(letters_in_centered) == len(letters_in_msg) + 1 - -def test_center_text_pad_equals(): - msg = 'foo' - pad = '=' - centered = cu.center_text(msg, pad=pad) - expected_center = ' ' + msg + ' ' - assert expected_center in centered - assert centered.startswith(pad) - assert centered.endswith(pad) - letters_in_centered = set(centered) - letters_in_msg = set(msg) - assert len(letters_in_centered) == len(letters_in_msg) + 2 +def test_align_text_fill_char_is_tab(): + text = 'foo' + fill_char = '\t' + width = 5 + aligned = cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) + assert aligned == text + ' ' + +def test_align_text_fill_char_is_too_long(): + text = 'foo' + fill_char = 'fill' + width = 5 + with pytest.raises(TypeError): + cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) +def test_align_text_fill_char_is_unprintable(): + text = 'foo' + fill_char = '\n' + width = 5 + with pytest.raises(ValueError): + cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) + +def test_align_text_has_tabs(): + text = '\t\tfoo' + fill_char = '-' + width = 10 + aligned = cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT, tab_width=2) + assert aligned == ' ' + 'foo' + '---' + +def test_align_text_blank(): + text = '' + fill_char = '-' + width = 5 + aligned = cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) + assert aligned == fill_char * width + +def test_align_text_wider_than_width(): + text = 'long' + fill_char = '-' + width = 3 + aligned = cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) + assert aligned == text + +def test_align_text_has_unprintable(): + text = 'foo\x02' + fill_char = '-' + width = 5 + with pytest.raises(ValueError): + cu.align_text(text, fill_char=fill_char, width=width, alignment=cu.TextAlignment.LEFT) + +def test_align_text_term_width(): + import shutil + from cmd2 import ansi + text = 'foo' + fill_char = ' ' + + term_width = shutil.get_terminal_size().columns + expected_fill = (term_width - ansi.style_aware_wcswidth(text)) * fill_char + + aligned = cu.align_text(text, fill_char=fill_char, alignment=cu.TextAlignment.LEFT) + assert aligned == text + expected_fill + +def test_align_left(): + text = 'foo' + fill_char = '-' + width = 5 + aligned = cu.align_left(text, fill_char=fill_char, width=width) + assert aligned == text + fill_char + fill_char + +def test_align_left_multiline(): + text = "foo\nshoes" + fill_char = '-' + width = 7 + aligned = cu.align_left(text, fill_char=fill_char, width=width) + assert aligned == ('foo----\n' + 'shoes--') + +def test_align_left_wide_text(): + text = '苹' + fill_char = '-' + width = 4 + aligned = cu.align_left(text, fill_char=fill_char, width=width) + assert aligned == text + fill_char + fill_char + +def test_align_left_wide_fill(): + text = 'foo' + fill_char = '苹' + width = 5 + aligned = cu.align_left(text, fill_char=fill_char, width=width) + assert aligned == text + fill_char + +def test_align_left_wide_fill_needs_padding(): + """Test when fill_char's display width does not divide evenly into gap""" + text = 'foo' + fill_char = '苹' + width = 6 + aligned = cu.align_left(text, fill_char=fill_char, width=width) + assert aligned == text + fill_char + ' ' + +def test_align_center(): + text = 'foo' + fill_char = '-' + width = 5 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == fill_char + text + fill_char + +def test_align_center_multiline(): + text = "foo\nshoes" + fill_char = '-' + width = 7 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == ('--foo--\n' + '-shoes-') + +def test_align_center_wide_text(): + text = '苹' + fill_char = '-' + width = 4 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == fill_char + text + fill_char + +def test_align_center_wide_fill(): + text = 'foo' + fill_char = '苹' + width = 7 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == fill_char + text + fill_char + +def test_align_center_wide_fill_needs_right_padding(): + """Test when fill_char's display width does not divide evenly into right gap""" + text = 'foo' + fill_char = '苹' + width = 8 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == fill_char + text + fill_char + ' ' + +def test_align_center_wide_fill_needs_left_and_right_padding(): + """Test when fill_char's display width does not divide evenly into either gap""" + text = 'foo' + fill_char = '苹' + width = 9 + aligned = cu.align_center(text, fill_char=fill_char, width=width) + assert aligned == fill_char + ' ' + text + fill_char + ' ' + +def test_align_right(): + text = 'foo' + fill_char = '-' + width = 5 + aligned = cu.align_right(text, fill_char=fill_char, width=width) + assert aligned == fill_char + fill_char + text + +def test_align_right_multiline(): + text = "foo\nshoes" + fill_char = '-' + width = 7 + aligned = cu.align_right(text, fill_char=fill_char, width=width) + assert aligned == ('----foo\n' + '--shoes') + +def test_align_right_wide_text(): + text = '苹' + fill_char = '-' + width = 4 + aligned = cu.align_right(text, fill_char=fill_char, width=width) + assert aligned == fill_char + fill_char + text + +def test_align_right_wide_fill(): + text = 'foo' + fill_char = '苹' + width = 5 + aligned = cu.align_right(text, fill_char=fill_char, width=width) + assert aligned == fill_char + text + +def test_align_right_wide_fill_needs_padding(): + """Test when fill_char's display width does not divide evenly into gap""" + text = 'foo' + fill_char = '苹' + width = 6 + aligned = cu.align_right(text, fill_char=fill_char, width=width) + assert aligned == fill_char + ' ' + text diff --git a/tests/transcripts/regex_set.txt b/tests/transcripts/regex_set.txt index fdcca3a8..17f43ede 100644 --- a/tests/transcripts/regex_set.txt +++ b/tests/transcripts/regex_set.txt @@ -4,7 +4,7 @@ # Regexes on prompts just make the trailing space obvious (Cmd) set -allow_ansi: /(Terminal|Always|Never)/ +allow_style: /(Terminal|Always|Never)/ continuation_prompt: >/ / debug: False echo: False |