summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/conftest.py13
-rw-r--r--tests/scripts/postcmds.txt2
-rw-r--r--tests/scripts/precmds.txt2
-rw-r--r--tests/test_ansi.py25
-rw-r--r--tests/test_argparse_completer.py4
-rwxr-xr-xtests/test_cmd2.py139
-rwxr-xr-xtests/test_history.py28
-rw-r--r--tests/test_run_pyscript.py27
-rw-r--r--tests/test_utils.py198
-rw-r--r--tests/transcripts/regex_set.txt2
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