refactor system tests

This commit is contained in:
2025-12-06 20:01:47 +03:00
parent 1d2ab6f6bb
commit dee328525d
7 changed files with 427 additions and 425 deletions
+2
View File
@@ -318,3 +318,5 @@ http-client.private.env.json
# Apifox Helper cache # Apifox Helper cache
.idea/.cache/.Apifox_Helper .idea/.cache/.Apifox_Helper
.idea/ApifoxUploaderProjectSetting.xml .idea/ApifoxUploaderProjectSetting.xml
.zed
+1 -1
View File
@@ -59,7 +59,7 @@ reportUnusedFunction = false
branch = true branch = true
omit = [ omit = [
"src/argenta/app/protocols.py", "src/argenta/app/protocols.py",
"src/argenta/command/exceptions.py", "src/argenta/*/exceptions.py",
"src/argenta/metrics/*" "src/argenta/metrics/*"
] ]
-11
View File
@@ -129,17 +129,6 @@ class Router:
command_handler.handling(response) command_handler.handling(response)
class CommandDecorator:
def __init__(self, router_instance: Router, command: Command):
self.router: Router = router_instance
self.command: Command = command
def __call__(self, handler_func: Callable[..., None]) -> Callable[..., None]:
_validate_func_args(handler_func)
self.router.command_handlers.add_handler(CommandHandler(handler_func, self.command))
return handler_func
def _structuring_input_flags(handled_command: Command, input_flags: InputFlags) -> Response: def _structuring_input_flags(handled_command: Command, input_flags: InputFlags) -> Response:
""" """
Private. Validates flags of input command Private. Validates flags of input command
@@ -1,10 +1,8 @@
import io
import re import re
import sys import sys
from unittest import TestCase from collections.abc import Iterator
from unittest.mock import MagicMock, patch
import _io import pytest
from argenta import App, Orchestrator, Router from argenta import App, Orchestrator, Router
from argenta.command import Command, PredefinedFlags from argenta.command import Command, PredefinedFlags
@@ -13,61 +11,143 @@ from argenta.command.flag.models import ValidationStatus
from argenta.response import Response from argenta.response import Response
class PatchedArgvTestCase(TestCase): @pytest.fixture(autouse=True)
def setUp(self): def patch_argv(monkeypatch: pytest.MonkeyPatch) -> None:
super().setUp() monkeypatch.setattr(sys, 'argv', ['program.py'])
self.patcher = patch.object(sys, 'argv', ['program.py'])
self.mock_argv = self.patcher.start()
self.addCleanup(self.patcher.stop)
class TestSystemHandlerNormalWork(PatchedArgvTestCase): def _mock_input(inputs: Iterator[str]) -> str:
@patch("builtins.input", side_effect=["help", "q"]) return next(inputs)
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_incorrect_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
# ============================================================================
# Tests for empty input handling
# ============================================================================
def test_empty_input_triggers_empty_command_handler(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test')) @router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command') print('test command')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}')) app.set_empty_command_handler(lambda: print('Empty input command'))
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn("\nUnknown command: help\n", output) assert "\nEmpty input command\n" in output
@patch("builtins.input", side_effect=["TeSt", "Q"]) # ============================================================================
@patch("sys.stdout", new_callable=io.StringIO) # Tests for unknown command handling
def test_input_incorrect_command2(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): # ============================================================================
def test_unknown_command_triggers_unknown_command_handler(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["help", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test')) @router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command') print('test command')
app = App(ignore_command_register=False, app = App(override_system_messages=True, print_func=print)
override_system_messages=True,
print_func=print)
app.include_router(router) app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}')) app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nUnknown command: TeSt\n', output) assert "\nUnknown command: help\n" in output
@patch("builtins.input", side_effect=["test --help", "q"]) def test_case_sensitive_command_triggers_unknown_command_handler(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["TeSt", "Q"])
def test_input_correct_command_with_unregistered_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command')
app = App(ignore_command_register=False, override_system_messages=True, print_func=print)
app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app)
output = capsys.readouterr().out
assert '\nUnknown command: TeSt\n' in output
def test_mixed_valid_and_unknown_commands_handled_correctly(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test", "some", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command')
app = App(override_system_messages=True, print_func=print)
app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app)
output = capsys.readouterr().out
assert re.search(r'\ntest command\n(.|\n)*\nUnknown command: some', output)
def test_multiple_commands_with_unknown_command_in_between(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test", "some", "more", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command')
@router.command(Command('more'))
def test1(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('more command')
app = App(override_system_messages=True, print_func=print)
app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app)
output = capsys.readouterr().out
assert re.search(r'\ntest command\n(.|\n)*\nUnknown command: some\n(.|\n)*\nmore command', output)
# ============================================================================
# Tests for unregistered flag handling
# ============================================================================
def test_unregistered_flag_without_value_is_accessible(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test --help", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@@ -77,19 +157,19 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if undefined_flag and undefined_flag.status == ValidationStatus.UNDEFINED: if undefined_flag and undefined_flag.status == ValidationStatus.UNDEFINED:
print(f'test command with undefined flag: {undefined_flag.string_entity}') print(f'test command with undefined flag: {undefined_flag.string_entity}')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\ntest command with undefined flag: --help\n', output) assert '\ntest command with undefined flag: --help\n' in output
@patch("builtins.input", side_effect=["test --port 22", "q"]) def test_unregistered_flag_with_value_is_accessible(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test --port 22", "q"])
def test_input_correct_command_with_unregistered_flag2(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@@ -101,19 +181,19 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
else: else:
raise raise
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\ntest command with undefined flag with value: --port 22\n', output) assert '\ntest command with undefined flag with value: --port 22\n' in output
@patch("builtins.input", side_effect=["test --host 192.168.32.1 --port 132", "q"]) def test_registered_and_unregistered_flags_coexist(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test --host 192.168.32.1 --port 132", "q"])
def test_input_correct_command_with_one_correct_flag_an_one_incorrect_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flags = Flags([PredefinedFlags.HOST]) flags = Flags([PredefinedFlags.HOST])
@@ -124,141 +204,62 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if undefined_flag and undefined_flag.status == ValidationStatus.UNDEFINED: if undefined_flag and undefined_flag.status == ValidationStatus.UNDEFINED:
print(f'connecting to host with flag: {undefined_flag.string_entity} {undefined_flag.input_value}') print(f'connecting to host with flag: {undefined_flag.string_entity} {undefined_flag.input_value}')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nconnecting to host with flag: --port 132\n', output) assert '\nconnecting to host with flag: --port 132\n' in output
@patch("builtins.input", side_effect=["test", "some", "q"]) # ============================================================================
@patch("sys.stdout", new_callable=io.StringIO) # Tests for incorrect flag syntax handling
def test_input_one_correct_command_and_one_incorrect_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): # ============================================================================
def test_flag_without_value_triggers_incorrect_syntax_handler(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test 535 --port", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test')) @router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command') print('test command')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertRegex(output, re.compile(r'\ntest command\n(.|\n)*\nUnknown command: some'))
@patch("builtins.input", side_effect=["test", "some", "more", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_two_correct_commands_and_one_incorrect_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command')
@router.command(Command('more'))
def test1(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'more command')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router)
app.set_unknown_command_handler(lambda command: print(f'Unknown command: {command.trigger}'))
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertRegex(output, re.compile(r'\ntest command\n(.|\n)*\nUnknown command: some\n(.|\n)*\nmore command'))
@patch("builtins.input", side_effect=["test 535 --port", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_correct_command_with_incorrect_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router) app.include_router(router)
app.set_incorrect_input_syntax_handler(lambda command: print(f'Incorrect flag syntax: "{command}"')) app.set_incorrect_input_syntax_handler(lambda command: print(f'Incorrect flag syntax: "{command}"'))
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn("\nIncorrect flag syntax: \"test 535 --port\"\n", output) assert "\nIncorrect flag syntax: \"test 535 --port\"\n" in output
@patch("builtins.input", side_effect=["", "q"]) # ============================================================================
@patch("sys.stdout", new_callable=io.StringIO) # Tests for repeated flag handling
def test_input_empty_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): # ============================================================================
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router)
app.set_empty_command_handler(lambda: print('Empty input command'))
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertIn("\nEmpty input command\n", output)
@patch("builtins.input", side_effect=["test --port 22 --port 33", "q"]) def test_repeated_flags_trigger_repeated_flags_handler(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test --port 22 --port 33", "q"])
def test_input_correct_command_with_repeated_flags(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test', flags=PredefinedFlags.PORT)) @router.command(Command('test', flags=PredefinedFlags.PORT))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command') print('test command')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
app.set_repeated_input_flags_handler(lambda command: print(f'Repeated input flags: "{command}"')) app.set_repeated_input_flags_handler(lambda command: print(f'Repeated input flags: "{command}"'))
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('Repeated input flags: "test --port 22 --port 33"', output) assert 'Repeated input flags: "test --port 22 --port 33"' in output
@patch("builtins.input", side_effect=["test --help", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_correct_command_with_unregistered_flag3(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
undefined_flag = response.input_flags.get_flag_by_name('help')
if undefined_flag and undefined_flag.status == ValidationStatus.UNDEFINED:
print(f'test command with undefined flag: {undefined_flag.string_entity}')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router)
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertIn('\ntest command with undefined flag: --help\n', output)
@@ -1,10 +1,8 @@
import io
import re import re
import sys import sys
from unittest import TestCase from collections.abc import Iterator
from unittest.mock import MagicMock, patch
import _io import pytest
from argenta import App, Orchestrator, Router from argenta import App, Orchestrator, Router
from argenta.command import Command, PredefinedFlags from argenta.command import Command, PredefinedFlags
@@ -14,59 +12,121 @@ from argenta.command.flag.models import PossibleValues, ValidationStatus
from argenta.response import Response from argenta.response import Response
class PatchedArgvTestCase(TestCase): @pytest.fixture(autouse=True)
def setUp(self): def patch_argv(monkeypatch: pytest.MonkeyPatch) -> None:
super().setUp() monkeypatch.setattr(sys, 'argv', ['program.py'])
self.patcher = patch.object(sys, 'argv', ['program.py'])
self.mock_argv = self.patcher.start()
self.addCleanup(self.patcher.stop)
class TestSystemHandlerNormalWork(PatchedArgvTestCase): def _mock_input(inputs: Iterator[str]) -> str:
@patch("builtins.input", side_effect=["test", "q"]) return next(inputs)
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_correct_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
# ============================================================================
# Tests for basic command execution
# ============================================================================
def test_simple_command_executes_successfully(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test')) @router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command') print('test command')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\ntest command\n', output) assert '\ntest command\n' in output
@patch("builtins.input", side_effect=["TeSt", "q"]) def test_case_insensitive_command_executes_when_enabled(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["TeSt", "q"])
def test_input_correct_command2(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
@router.command(Command('test')) @router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction] def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command') print('test command')
app = App(ignore_command_register=True, app = App(ignore_command_register=True, override_system_messages=True, print_func=print)
override_system_messages=True,
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\ntest command\n', output) assert '\ntest command\n' in output
@patch("builtins.input", side_effect=["test --help", "q"]) def test_two_commands_execute_sequentially(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test", "some", "q"])
def test_input_correct_command_with_custom_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command')
@router.command(Command('some'))
def test2(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('some command')
app = App(override_system_messages=True, print_func=print)
app.include_router(router)
orchestrator.start_polling(app)
output = capsys.readouterr().out
assert re.search(r'\ntest command\n(.|\n)*\nsome command\n', output)
def test_three_commands_execute_sequentially(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test", "some", "more", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('test command')
@router.command(Command('some'))
def test1(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('some command')
@router.command(Command('more'))
def test2(_response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print('more command')
app = App(override_system_messages=True, print_func=print)
app.include_router(router)
orchestrator.start_polling(app)
output = capsys.readouterr().out
assert re.search(r'\ntest command\n(.|\n)*\nsome command\n(.|\n)*\nmore command', output)
# ============================================================================
# Tests for custom flag handling
# ============================================================================
def test_custom_flag_without_value_is_recognized(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test --help", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flag = Flag('help', prefix='--', possible_values=PossibleValues.NEITHER) flag = Flag('help', prefix='--', possible_values=PossibleValues.NEITHER)
@@ -77,18 +137,19 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if valid_flag and valid_flag.status == ValidationStatus.VALID: if valid_flag and valid_flag.status == ValidationStatus.VALID:
print(f'\nhelp for {valid_flag.name} flag\n') print(f'\nhelp for {valid_flag.name} flag\n')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nhelp for help flag\n', output) assert '\nhelp for help flag\n' in output
def test_custom_flag_with_regex_validation_accepts_valid_value(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test --port 22", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
@patch("builtins.input", side_effect=["test --port 22", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_correct_command_with_custom_flag2(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flag = Flag('port', prefix='--', possible_values=re.compile(r'^\d{1,5}$')) flag = Flag('port', prefix='--', possible_values=re.compile(r'^\d{1,5}$'))
@@ -99,22 +160,24 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if valid_flag and valid_flag.status == ValidationStatus.VALID: if valid_flag and valid_flag.status == ValidationStatus.VALID:
print(f'flag value for {valid_flag.name} flag : {valid_flag.input_value}') print(f'flag value for {valid_flag.name} flag : {valid_flag.input_value}')
app = App( app = App(override_system_messages=True, repeat_command_groups_printing=True, print_func=print)
override_system_messages=True,
repeat_command_groups_printing=True,
print_func=print
)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nflag value for port flag : 22\n', output) assert '\nflag value for port flag : 22\n' in output
@patch("builtins.input", side_effect=["test -H", "q"]) # ============================================================================
@patch("sys.stdout", new_callable=io.StringIO) # Tests for predefined flag handling
def test_input_correct_command_with_default_flag(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): # ============================================================================
def test_predefined_short_help_flag_is_recognized(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test -H", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flag = PredefinedFlags.SHORT_HELP flag = PredefinedFlags.SHORT_HELP
@@ -125,19 +188,19 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if valid_flag and valid_flag.status == ValidationStatus.VALID: if valid_flag and valid_flag.status == ValidationStatus.VALID:
print(f'help for {valid_flag.name} flag') print(f'help for {valid_flag.name} flag')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nhelp for H flag\n', output) assert '\nhelp for H flag\n' in output
@patch("builtins.input", side_effect=["test --info", "q"]) def test_predefined_info_flag_is_recognized(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test --info", "q"])
def test_input_correct_command_with_default_flag2(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flag = PredefinedFlags.INFO flag = PredefinedFlags.INFO
@@ -148,19 +211,19 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if valid_flag and valid_flag.status == ValidationStatus.VALID: if valid_flag and valid_flag.status == ValidationStatus.VALID:
print('info about test command') print('info about test command')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\ninfo about test command\n', output) assert '\ninfo about test command\n' in output
@patch("builtins.input", side_effect=["test --host 192.168.0.1", "q"]) def test_predefined_host_flag_with_value_is_recognized(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
@patch("sys.stdout", new_callable=io.StringIO) inputs = iter(["test --host 192.168.0.1", "q"])
def test_input_correct_command_with_default_flag3(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flag = PredefinedFlags.HOST flag = PredefinedFlags.HOST
@@ -171,19 +234,24 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if valid_flag and valid_flag.status == ValidationStatus.VALID: if valid_flag and valid_flag.status == ValidationStatus.VALID:
print(f'connecting to host {valid_flag.input_value}') print(f'connecting to host {valid_flag.input_value}')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nconnecting to host 192.168.0.1\n', output) assert '\nconnecting to host 192.168.0.1\n' in output
@patch("builtins.input", side_effect=["test --host 192.168.32.1 --port 132", "q"]) # ============================================================================
@patch("sys.stdout", new_callable=io.StringIO) # Tests for multiple flag handling
def test_input_correct_command_with_two_flags(self, mock_stdout: _io.StringIO, magick_mock: MagicMock): # ============================================================================
def test_two_predefined_flags_are_recognized_together(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
inputs = iter(["test --host 192.168.32.1 --port 132", "q"])
monkeypatch.setattr('builtins.input', lambda _prompt="": _mock_input(inputs))
router = Router() router = Router()
orchestrator = Orchestrator() orchestrator = Orchestrator()
flags = Flags([PredefinedFlags.HOST, PredefinedFlags.PORT]) flags = Flags([PredefinedFlags.HOST, PredefinedFlags.PORT])
@@ -195,63 +263,10 @@ class TestSystemHandlerNormalWork(PatchedArgvTestCase):
if (host_flag and host_flag.status == ValidationStatus.VALID) and (port_flag and port_flag.status == ValidationStatus.VALID): if (host_flag and host_flag.status == ValidationStatus.VALID) and (port_flag and port_flag.status == ValidationStatus.VALID):
print(f'connecting to host {host_flag.input_value} and port {port_flag.input_value}') print(f'connecting to host {host_flag.input_value} and port {port_flag.input_value}')
app = App(override_system_messages=True, app = App(override_system_messages=True, print_func=print)
print_func=print)
app.include_router(router) app.include_router(router)
orchestrator.start_polling(app) orchestrator.start_polling(app)
output = mock_stdout.getvalue() output = capsys.readouterr().out
self.assertIn('\nconnecting to host 192.168.32.1 and port 132\n', output) assert '\nconnecting to host 192.168.32.1 and port 132\n' in output
@patch("builtins.input", side_effect=["test", "some", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_two_correct_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command')
@router.command(Command('some'))
def test2(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'some command')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router)
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertRegex(output, re.compile(r'\ntest command\n(.|\n)*\nsome command\n'))
@patch("builtins.input", side_effect=["test", "some", "more", "q"])
@patch("sys.stdout", new_callable=io.StringIO)
def test_input_three_correct_command(self, mock_stdout: _io.StringIO, magick_mock: MagicMock):
router = Router()
orchestrator = Orchestrator()
@router.command(Command('test'))
def test(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'test command')
@router.command(Command('some'))
def test1(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'some command')
@router.command(Command('more'))
def test2(response: Response) -> None: # pyright: ignore[reportUnusedFunction]
print(f'more command')
app = App(override_system_messages=True,
print_func=print)
app.include_router(router)
orchestrator.start_polling(app)
output = mock_stdout.getvalue()
self.assertRegex(output, re.compile(r'\ntest command\n(.|\n)*\nsome command\n(.|\n)*\nmore command'))
-1
View File
@@ -1,5 +1,4 @@
import re import re
from sys import flags
from argenta.command.flag import Flag, InputFlag, PossibleValues from argenta.command.flag import Flag, InputFlag, PossibleValues
from argenta.command.flag.flags import Flags, InputFlags from argenta.command.flag.flags import Flags, InputFlags
+1 -5
View File
@@ -1,5 +1,6 @@
import re import re
import pytest import pytest
from pytest import CaptureFixture
from argenta.command import Command, InputCommand from argenta.command import Command, InputCommand
from argenta.command.flag import Flag, InputFlag from argenta.command.flag import Flag, InputFlag
@@ -142,11 +143,6 @@ def test_wrong_typehint(capsys: pytest.CaptureFixture[str]):
def test_missing_typehint(capsys: pytest.CaptureFixture[str]): def test_missing_typehint(capsys: pytest.CaptureFixture[str]):
def func(response): pass # pyright: ignore[reportMissingParameterType, reportUnknownParameterType] def func(response): pass # pyright: ignore[reportMissingParameterType, reportUnknownParameterType]
_validate_func_args(func) # pyright: ignore[reportUnknownArgumentType] _validate_func_args(func) # pyright: ignore[reportUnknownArgumentType]
output = capsys.readouterr() output = capsys.readouterr()
assert output.out == '' assert output.out == ''