summaryrefslogtreecommitdiff
path: root/tests/test_completion.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_completion.py')
-rw-r--r--tests/test_completion.py217
1 files changed, 217 insertions, 0 deletions
diff --git a/tests/test_completion.py b/tests/test_completion.py
index efc32986..70f77d0a 100644
--- a/tests/test_completion.py
+++ b/tests/test_completion.py
@@ -8,10 +8,13 @@ file system paths, and shell commands.
Copyright 2017 Todd Leonhardt <todd.leonhardt@gmail.com>
Released under MIT license, see LICENSE file
"""
+import argparse
import os
+import readline
import sys
import cmd2
+import mock
import pytest
@@ -35,6 +38,100 @@ def test_cmd2_command_completion_single_end(cmd2_app):
# It is at end of line, so extra space is present
assert cmd2_app.completenames(text, line, begidx, endidx) == ['help ']
+def test_complete_command_single_end(cmd2_app):
+ text = 'he'
+ line = 'he'
+ state = 0
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ # Run the readline tab-completion function with readline mocks in place
+ completion = cmd2_app.complete(text, state)
+ assert completion == 'help '
+
+def test_complete_command_invalid_state(cmd2_app):
+ text = 'he'
+ line = 'he'
+ state = 1
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ # Run the readline tab-completion function with readline mocks in place get None
+ completion = cmd2_app.complete(text, state)
+ assert completion is None
+
+def test_complete_empty_arg(cmd2_app):
+ text = ''
+ line = 'help '
+ state = 0
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ # Run the readline tab-completion function with readline mocks in place
+ completion = cmd2_app.complete(text, state)
+
+ assert completion == cmd2_app.complete_help(text, line, begidx, endidx)[0]
+
+def test_complete_bogus_command(cmd2_app):
+ text = ''
+ line = 'fizbuzz '
+ state = 0
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ # Run the readline tab-completion function with readline mocks in place
+ completion = cmd2_app.complete(text, state)
+
+ assert completion is None
+
def test_cmd2_command_completion_is_case_insensitive_by_default(cmd2_app):
text = 'HE'
line = 'HE'
@@ -323,3 +420,123 @@ def test_parseline_expands_shortcuts(cmd2_app):
assert command == 'shell'
assert args == 'cat foobar.txt'
assert line.replace('!', 'shell ') == out_line
+
+
+class SubcommandsExample(cmd2.Cmd):
+ """ Example cmd2 application where we a base command which has a couple subcommands."""
+
+ def __init__(self):
+ cmd2.Cmd.__init__(self)
+
+ # sub-command functions for the base command
+ def base_foo(self, args):
+ """foo subcommand of base command"""
+ self.poutput(args.x * args.y)
+
+ def base_bar(self, args):
+ """bar sucommand of base command"""
+ self.poutput('((%s))' % args.z)
+
+ # create the top-level parser for the base command
+ base_parser = argparse.ArgumentParser(prog='base')
+ base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help')
+
+ # create the parser for the "foo" sub-command
+ parser_foo = base_subparsers.add_parser('foo', help='foo help')
+ parser_foo.add_argument('-x', type=int, default=1, help='integer')
+ parser_foo.add_argument('y', type=float, help='float')
+ parser_foo.set_defaults(func=base_foo)
+
+ # create the parser for the "bar" sub-command
+ parser_bar = base_subparsers.add_parser('bar', help='bar help')
+ parser_bar.add_argument('z', help='string')
+ parser_bar.set_defaults(func=base_bar)
+
+ # Create a list of subcommand names, which is used to enable tab-completion of sub-commands
+ subcommands = ['foo', 'bar']
+
+ @cmd2.with_argparser(base_parser, subcommands)
+ def do_base(self, args):
+ """Base command help"""
+ try:
+ # Call whatever sub-command function was selected
+ args.func(self, args)
+ except AttributeError:
+ # No sub-command was provided, so as called
+ self.do_help('base')
+
+
+@pytest.fixture
+def sc_app():
+ app = SubcommandsExample()
+ return app
+
+
+def test_cmd2_subcommand_completion_single_end(sc_app):
+ text = 'f'
+ line = 'base f'
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ # It is at end of line, so extra space is present
+ assert sc_app.complete_subcommand(text, line, begidx, endidx) == ['foo ']
+
+def test_cmd2_subcommand_completion_single_mid(sc_app):
+ text = 'f'
+ line = 'base f'
+ endidx = len(line) - 1
+ begidx = endidx - len(text)
+
+ # It is at end of line, so extra space is present
+ assert sc_app.complete_subcommand(text, line, begidx, endidx) == ['foo']
+
+def test_cmd2_subcommand_completion_multiple(sc_app):
+ text = ''
+ line = 'base '
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ # It is at end of line, so extra space is present
+ assert sc_app.complete_subcommand(text, line, begidx, endidx) == ['foo', 'bar']
+
+def test_cmd2_subcommand_completion_nomatch(sc_app):
+ text = 'z'
+ line = 'base z'
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ # It is at end of line, so extra space is present
+ assert sc_app.complete_subcommand(text, line, begidx, endidx) == []
+
+def test_cmd2_subcommand_completion_after_subcommand(sc_app):
+ text = 'f'
+ line = 'base foo f'
+ endidx = len(line)
+ begidx = endidx - len(text)
+
+ # It is at end of line, so extra space is present
+ assert sc_app.complete_subcommand(text, line, begidx, endidx) == []
+
+
+def test_complete_subcommand_single_end(sc_app):
+ text = 'f'
+ line = 'base f'
+ endidx = len(line)
+ begidx = endidx - len(text)
+ state = 0
+
+ def get_line():
+ return line
+
+ def get_begidx():
+ return begidx
+
+ def get_endidx():
+ return endidx
+
+ with mock.patch.object(readline, 'get_line_buffer', get_line):
+ with mock.patch.object(readline, 'get_begidx', get_begidx):
+ with mock.patch.object(readline, 'get_endidx', get_endidx):
+ # Run the readline tab-completion function with readline mocks in place
+ completion = sc_app.complete(text, state)
+ assert completion == 'foo '