mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 10:05:28 +03:00
feat: impl docs (#4)
The entire public api is covered with documentation in two languages - Russian and English. the library now supports the latest three versions of python - 3.12, 3.13 and 3.14 minor design changes: now, when a Boolean flag is entered, its value is an empty string, not None. tests have been adapted to the supported versions of python, readmi has been redesigned in two languages, German is no longer available.
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
from argenta.command.models import InputCommand, Command
|
||||
from argenta.app import App
|
||||
|
||||
import unittest
|
||||
|
||||
from argenta.app import App
|
||||
from argenta.command.models import Command, InputCommand
|
||||
from argenta.router import Router
|
||||
|
||||
|
||||
|
||||
+201
-116
@@ -1,18 +1,21 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
from argparse import Namespace
|
||||
import sys
|
||||
from unittest.mock import call
|
||||
|
||||
import pytest
|
||||
|
||||
from argenta.orchestrator.argparser.arguments.models import (BaseArgument,
|
||||
BooleanArgument,
|
||||
InputArgument,
|
||||
ValueArgument)
|
||||
from argenta.orchestrator.argparser.entity import ArgParser, ArgSpace
|
||||
from argenta.orchestrator.argparser.arguments.models import (
|
||||
ValueArgument,
|
||||
BooleanArgument,
|
||||
InputArgument,
|
||||
BaseArgument
|
||||
)
|
||||
|
||||
|
||||
class TestArgumentClasses(unittest.TestCase):
|
||||
class TestArgumentCreation:
|
||||
"""Tests for the creation and attribute validation of argument model classes."""
|
||||
|
||||
def test_value_argument_creation(self):
|
||||
"""Ensures ValueArgument instances are created with correct attributes."""
|
||||
arg = ValueArgument(
|
||||
name="test_arg",
|
||||
prefix="--",
|
||||
@@ -20,145 +23,227 @@ class TestArgumentClasses(unittest.TestCase):
|
||||
possible_values=["one", "two"],
|
||||
default="one",
|
||||
is_required=True,
|
||||
is_deprecated=False
|
||||
is_deprecated=False,
|
||||
)
|
||||
self.assertEqual(arg.name, "test_arg")
|
||||
self.assertEqual(arg.prefix, "--")
|
||||
self.assertEqual(arg.help, "A test argument.")
|
||||
self.assertEqual(arg.possible_values, ["one", "two"])
|
||||
self.assertEqual(arg.default, "one")
|
||||
self.assertTrue(arg.is_required)
|
||||
self.assertFalse(arg.is_deprecated)
|
||||
self.assertEqual(arg.action, "store")
|
||||
self.assertEqual(arg.string_entity, "--test_arg")
|
||||
assert arg.name == "test_arg"
|
||||
assert arg.prefix == "--"
|
||||
assert arg.help == "A test argument."
|
||||
assert arg.possible_values == ["one", "two"]
|
||||
assert arg.default == "one"
|
||||
assert arg.is_required is True
|
||||
assert arg.is_deprecated is False
|
||||
assert arg.action == "store"
|
||||
assert arg.string_entity == "--test_arg"
|
||||
|
||||
def test_boolean_argument_creation(self):
|
||||
"""Ensures BooleanArgument instances are created with correct attributes."""
|
||||
arg = BooleanArgument(
|
||||
name="verbose",
|
||||
prefix="-",
|
||||
help="Enable verbose mode.",
|
||||
is_deprecated=True
|
||||
name="verbose", prefix="-", help="Enable verbose mode.", is_deprecated=True
|
||||
)
|
||||
self.assertEqual(arg.name, "verbose")
|
||||
self.assertEqual(arg.prefix, "-")
|
||||
self.assertEqual(arg.help, "Enable verbose mode.")
|
||||
self.assertTrue(arg.is_deprecated)
|
||||
self.assertEqual(arg.action, "store_true")
|
||||
self.assertEqual(arg.string_entity, "-verbose")
|
||||
assert arg.name == "verbose"
|
||||
assert arg.prefix == "-"
|
||||
assert arg.help == "Enable verbose mode."
|
||||
assert arg.is_deprecated is True
|
||||
assert arg.action == "store_true"
|
||||
assert arg.string_entity == "-verbose"
|
||||
|
||||
def test_input_argument_creation(self):
|
||||
"""Ensures InputArgument instances are created with correct attributes."""
|
||||
arg = InputArgument(
|
||||
name="file",
|
||||
value="/path/to/file",
|
||||
founder_class=ValueArgument
|
||||
name="file", value="/path/to/file", founder_class=ValueArgument
|
||||
)
|
||||
self.assertEqual(arg.name, "file")
|
||||
self.assertEqual(arg.value, "/path/to/file")
|
||||
self.assertEqual(arg.founder_class, ValueArgument)
|
||||
assert arg.name == "file"
|
||||
assert arg.value == "/path/to/file"
|
||||
assert arg.founder_class is ValueArgument
|
||||
|
||||
|
||||
class TestArgParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.value_arg = ValueArgument(name="config", help="Path to config file")
|
||||
self.bool_arg = BooleanArgument(name="debug", help="Enable debug mode")
|
||||
self.processed_args = [self.value_arg, self.bool_arg]
|
||||
class TestArgSpace:
|
||||
"""Tests for the ArgSpace class, which holds parsed argument values."""
|
||||
|
||||
def test_argparser_initialization(self):
|
||||
parser = ArgParser(
|
||||
processed_args=self.processed_args,
|
||||
name="TestApp",
|
||||
description="A test application.",
|
||||
epilog="Test epilog."
|
||||
)
|
||||
self.assertEqual(parser.name, "TestApp")
|
||||
self.assertEqual(parser.description, "A test application.")
|
||||
self.assertEqual(parser.epilog, "Test epilog.")
|
||||
self.assertEqual(parser.processed_args, self.processed_args)
|
||||
@pytest.fixture
|
||||
def mock_arguments(self) -> list[InputArgument]:
|
||||
"""Provides a list of mock InputArgument objects for testing."""
|
||||
return [
|
||||
InputArgument(name="arg1", value="val1", founder_class=ValueArgument),
|
||||
InputArgument(name="arg2", value=True, founder_class=BooleanArgument),
|
||||
InputArgument(name="arg3", value="val3", founder_class=ValueArgument),
|
||||
]
|
||||
|
||||
@patch('argenta.orchestrator.argparser.entity.ArgumentParser.parse_args')
|
||||
def test_parse_args(self, mock_parse_args: MagicMock):
|
||||
mock_namespace = Namespace(config='config.json', debug=True)
|
||||
mock_parse_args.return_value = mock_namespace
|
||||
@pytest.fixture
|
||||
def arg_space(self, mock_arguments: list[InputArgument]) -> ArgSpace:
|
||||
"""Provides a pre-populated ArgSpace instance."""
|
||||
return ArgSpace(all_arguments=mock_arguments)
|
||||
|
||||
parser = ArgParser(processed_args=self.processed_args)
|
||||
arg_space = parser.parse_args()
|
||||
def test_initialization(self, arg_space: ArgSpace, mock_arguments: list[InputArgument]):
|
||||
"""Tests if ArgSpace is initialized correctly with a list of arguments."""
|
||||
assert len(arg_space.all_arguments) == 3
|
||||
assert arg_space.all_arguments == mock_arguments
|
||||
|
||||
self.assertIsInstance(arg_space, ArgSpace)
|
||||
self.assertEqual(len(arg_space.all_arguments), 2)
|
||||
def test_get_by_name(self, arg_space: ArgSpace, mock_arguments: list[InputArgument]):
|
||||
"""Tests retrieving an argument by its name."""
|
||||
found_arg = arg_space.get_by_name("arg1")
|
||||
assert found_arg is not None
|
||||
assert found_arg == mock_arguments[0]
|
||||
|
||||
def test_get_by_name_not_found(self, arg_space: ArgSpace):
|
||||
"""Tests that get_by_name returns None for a non-existent argument."""
|
||||
found_arg = arg_space.get_by_name("non_existent_arg")
|
||||
assert found_arg is None
|
||||
|
||||
def test_get_by_type(self, arg_space: ArgSpace, mock_arguments: list[InputArgument]):
|
||||
"""Tests retrieving arguments based on their founder class type."""
|
||||
value_args = arg_space.get_by_type(ValueArgument)
|
||||
assert len(value_args) == 2
|
||||
assert mock_arguments[0] in value_args
|
||||
assert mock_arguments[2] in value_args
|
||||
|
||||
bool_args = arg_space.get_by_type(BooleanArgument)
|
||||
assert len(bool_args) == 1
|
||||
assert mock_arguments[1] in bool_args
|
||||
|
||||
def test_get_by_type_not_found(self, arg_space: ArgSpace):
|
||||
"""Tests that get_by_type returns an empty list for an unused argument type."""
|
||||
class OtherArgument(BaseArgument):
|
||||
pass
|
||||
other_args = arg_space.get_by_type(OtherArgument)
|
||||
assert other_args == []
|
||||
|
||||
def test_from_namespace(self):
|
||||
"""Tests the class method for creating an ArgSpace from an argparse.Namespace."""
|
||||
namespace = Namespace(config="config.json", debug=True, verbose=False)
|
||||
processed_args = [
|
||||
ValueArgument(name="config", prefix="--"),
|
||||
BooleanArgument(name="debug", prefix="-"),
|
||||
BooleanArgument(name="verbose", prefix="-"),
|
||||
]
|
||||
|
||||
arg_space = ArgSpace.from_namespace(namespace, processed_args)
|
||||
assert len(arg_space.all_arguments) == 3
|
||||
|
||||
config_arg = arg_space.get_by_name('config')
|
||||
debug_arg = arg_space.get_by_name('debug')
|
||||
|
||||
self.assertIsNotNone(config_arg)
|
||||
if config_arg:
|
||||
self.assertEqual(config_arg.value, 'config.json')
|
||||
self.assertEqual(config_arg.founder_class, ValueArgument)
|
||||
assert config_arg is not None
|
||||
assert config_arg.value == "config.json"
|
||||
assert config_arg.founder_class is ValueArgument
|
||||
|
||||
self.assertIsNotNone(debug_arg)
|
||||
if debug_arg:
|
||||
self.assertTrue(debug_arg.value)
|
||||
self.assertEqual(debug_arg.founder_class, BooleanArgument)
|
||||
assert debug_arg is not None
|
||||
assert debug_arg.value is True
|
||||
assert debug_arg.founder_class is BooleanArgument
|
||||
|
||||
|
||||
class TestArgSpace(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.input_arg1 = InputArgument(name="arg1", value="val1", founder_class=ValueArgument)
|
||||
self.input_arg2 = InputArgument(name="arg2", value="val2", founder_class=BooleanArgument)
|
||||
self.input_arg3 = InputArgument(name="arg3", value="val3", founder_class=ValueArgument)
|
||||
self.arg_space = ArgSpace(all_arguments=[self.input_arg1, self.input_arg2, self.input_arg3])
|
||||
class TestArgParser:
|
||||
"""Tests for the ArgParser class, which orchestrates argument parsing."""
|
||||
|
||||
def test_argspace_initialization(self):
|
||||
self.assertEqual(len(self.arg_space.all_arguments), 3)
|
||||
self.assertIn(self.input_arg1, self.arg_space.all_arguments)
|
||||
self.assertIn(self.input_arg2, self.arg_space.all_arguments)
|
||||
self.assertIn(self.input_arg3, self.arg_space.all_arguments)
|
||||
@pytest.fixture
|
||||
def value_arg(self) -> ValueArgument:
|
||||
"""Provides a sample ValueArgument."""
|
||||
return ValueArgument(name="config", help="Path to config file", default="dev.json", is_required=False, possible_values=["dev.json", "prod.json"])
|
||||
|
||||
def test_get_by_name(self):
|
||||
found_arg = self.arg_space.get_by_name("arg1")
|
||||
self.assertIsNotNone(found_arg)
|
||||
if found_arg:
|
||||
self.assertEqual(found_arg, self.input_arg1)
|
||||
@pytest.fixture
|
||||
def bool_arg(self) -> BooleanArgument:
|
||||
"""Provides a sample BooleanArgument."""
|
||||
return BooleanArgument(name="debug", help="Enable debug mode")
|
||||
|
||||
def test_get_by_name_not_found(self):
|
||||
found_arg = self.arg_space.get_by_name("non_existent_arg")
|
||||
self.assertIsNone(found_arg)
|
||||
@pytest.fixture
|
||||
def processed_args(self, value_arg: ValueArgument, bool_arg: BooleanArgument) -> list:
|
||||
"""Provides a list of processed arguments."""
|
||||
return [value_arg, bool_arg]
|
||||
|
||||
def test_get_by_type(self):
|
||||
value_args = self.arg_space.get_by_type(ValueArgument)
|
||||
self.assertEqual(len(value_args), 2)
|
||||
self.assertIn(self.input_arg1, value_args)
|
||||
self.assertIn(self.input_arg3, value_args)
|
||||
def test_initialization(self, processed_args: list):
|
||||
"""Tests that the ArgParser constructor correctly assigns attributes."""
|
||||
parser = ArgParser(
|
||||
processed_args=processed_args,
|
||||
name="TestApp",
|
||||
description="A test application.",
|
||||
epilog="Test epilog.",
|
||||
)
|
||||
assert parser.name == "TestApp"
|
||||
assert parser.description == "A test application."
|
||||
assert parser.epilog == "Test epilog."
|
||||
assert parser.processed_args == processed_args
|
||||
assert isinstance(parser.parsed_argspace, ArgSpace)
|
||||
assert parser.parsed_argspace.all_arguments == []
|
||||
|
||||
bool_args = self.arg_space.get_by_type(BooleanArgument)
|
||||
self.assertEqual(len(bool_args), 1)
|
||||
self.assertIn(self.input_arg2, bool_args)
|
||||
@pytest.mark.skipif(sys.version_info < (3, 13), reason="requires python3.13 or higher")
|
||||
def test_register_args(self, mocker, value_arg: ValueArgument, bool_arg: BooleanArgument):
|
||||
"""Tests that arguments are correctly registered with the underlying ArgumentParser."""
|
||||
mock_add_argument = mocker.patch("argparse.ArgumentParser.add_argument")
|
||||
|
||||
def test_get_by_type_not_found(self):
|
||||
class OtherArgument(BaseArgument):
|
||||
pass
|
||||
parser = ArgParser(processed_args=[value_arg, bool_arg])
|
||||
|
||||
other_args = self.arg_space.get_by_type(OtherArgument)
|
||||
self.assertEqual(len(other_args), 0)
|
||||
|
||||
def test_from_namespace(self):
|
||||
namespace = Namespace(arg1="val1", debug=True)
|
||||
processed_args = [
|
||||
ValueArgument(name="arg1", prefix="--"),
|
||||
BooleanArgument(name="debug", prefix="-")
|
||||
expected_calls = [
|
||||
# Call for the ValueArgument
|
||||
call(
|
||||
value_arg.string_entity,
|
||||
action=value_arg.action,
|
||||
help=value_arg.help,
|
||||
default=value_arg.default,
|
||||
choices=value_arg.possible_values,
|
||||
required=value_arg.is_required,
|
||||
deprecated=value_arg.is_deprecated
|
||||
),
|
||||
# Call for the BooleanArgument
|
||||
call(
|
||||
bool_arg.string_entity,
|
||||
action=bool_arg.action,
|
||||
help=bool_arg.help,
|
||||
deprecated=bool_arg.is_deprecated
|
||||
)
|
||||
]
|
||||
mock_add_argument.assert_has_calls(expected_calls, any_order=True)
|
||||
|
||||
@pytest.mark.skipif(sys.version_info > (3, 12), reason='for more latest python version has been other test')
|
||||
def test_register_args(self, mocker, value_arg: ValueArgument, bool_arg: BooleanArgument):
|
||||
"""Tests that arguments are correctly registered with the underlying ArgumentParser."""
|
||||
mock_add_argument = mocker.patch("argparse.ArgumentParser.add_argument")
|
||||
|
||||
arg_space = ArgSpace.from_namespace(namespace, processed_args)
|
||||
self.assertEqual(len(arg_space.all_arguments), 2)
|
||||
parser = ArgParser(processed_args=[value_arg, bool_arg])
|
||||
|
||||
arg1 = arg_space.get_by_name('arg1')
|
||||
expected_calls = [
|
||||
# Call for the ValueArgument
|
||||
call(
|
||||
value_arg.string_entity,
|
||||
action=value_arg.action,
|
||||
help=value_arg.help,
|
||||
default=value_arg.default,
|
||||
choices=value_arg.possible_values,
|
||||
required=value_arg.is_required
|
||||
),
|
||||
# Call for the BooleanArgument
|
||||
call(
|
||||
bool_arg.string_entity,
|
||||
action=bool_arg.action,
|
||||
help=bool_arg.help
|
||||
)
|
||||
]
|
||||
mock_add_argument.assert_has_calls(expected_calls, any_order=True)
|
||||
|
||||
def test_parse_args_populates_argspace(self, mocker, processed_args: list[ValueArgument | BooleanArgument]):
|
||||
"""Tests that _parse_args correctly calls the parser and populates the ArgSpace."""
|
||||
# 1. Mock the return value of the internal argparse instance
|
||||
mock_namespace = Namespace(config='config.json', debug=True)
|
||||
mocker.patch(
|
||||
'argparse.ArgumentParser.parse_args',
|
||||
return_value=mock_namespace
|
||||
)
|
||||
|
||||
# 2. Initialize the parser and call the method under test
|
||||
parser = ArgParser(processed_args=processed_args)
|
||||
parser._parse_args() # Test the private method that contains the logic
|
||||
|
||||
# 3. Assert the results
|
||||
arg_space = parser.parsed_argspace
|
||||
assert isinstance(arg_space, ArgSpace)
|
||||
assert len(arg_space.all_arguments) == 2
|
||||
|
||||
config_arg = arg_space.get_by_name('config')
|
||||
debug_arg = arg_space.get_by_name('debug')
|
||||
|
||||
self.assertIsNotNone(arg1)
|
||||
if arg1:
|
||||
self.assertEqual(arg1.value, "val1")
|
||||
self.assertEqual(arg1.founder_class, ValueArgument)
|
||||
assert config_arg is not None
|
||||
assert config_arg.value == 'config.json'
|
||||
assert config_arg.founder_class is ValueArgument
|
||||
|
||||
self.assertIsNotNone(debug_arg)
|
||||
if debug_arg:
|
||||
self.assertTrue(debug_arg.value)
|
||||
self.assertEqual(debug_arg.founder_class, BooleanArgument)
|
||||
assert debug_arg is not None
|
||||
assert debug_arg.value is True
|
||||
assert debug_arg.founder_class is BooleanArgument
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
import os
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
# Since readline is not available on all platforms (e.g., Windows) for testing,
|
||||
# it is mocked for all tests.
|
||||
readline_mock = MagicMock()
|
||||
|
||||
# We patch the module where it's imported, not where it's defined.
|
||||
@pytest.fixture
|
||||
def mock_readline():
|
||||
"""Fixture to provide a mock of the `readline` module."""
|
||||
with patch('argenta.app.autocompleter.entity.readline', readline_mock) as mock:
|
||||
# This nested state simulates readline's internal history list.
|
||||
_history = []
|
||||
|
||||
def add_history(item: str) -> None:
|
||||
_history.append(item)
|
||||
|
||||
def get_history_item(index: int) -> str | None:
|
||||
# readline history is 1-based.
|
||||
if 1 <= index <= len(_history):
|
||||
return _history[index - 1]
|
||||
return None
|
||||
|
||||
def get_current_history_length() -> int:
|
||||
return len(_history)
|
||||
|
||||
def clear_history() -> None:
|
||||
_history.clear()
|
||||
|
||||
# Reset all mocks and the internal history before each test.
|
||||
mock.reset_mock()
|
||||
clear_history()
|
||||
|
||||
# Apply side effects to mock functions to simulate real behavior.
|
||||
mock.add_history.side_effect = add_history
|
||||
mock.get_history_item.side_effect = get_history_item
|
||||
mock.get_current_history_length.side_effect = get_current_history_length
|
||||
|
||||
# Provide a default return value for functions that are read from.
|
||||
mock.get_completer_delims.return_value = " "
|
||||
|
||||
yield mock
|
||||
|
||||
# We import the class under test after setting up the patch context if needed,
|
||||
# or ensure patches target the correct import location.
|
||||
from argenta.app.autocompleter.entity import (AutoCompleter,
|
||||
_get_history_items,
|
||||
_is_command_exist)
|
||||
|
||||
|
||||
class TestAutoCompleter:
|
||||
"""Test suite for the AutoCompleter class."""
|
||||
HISTORY_FILE = "test_history.txt"
|
||||
COMMANDS = ["start", "stop", "status"]
|
||||
|
||||
def test_initialization(self):
|
||||
"""Tests that the constructor correctly assigns attributes."""
|
||||
completer = AutoCompleter(history_filename=self.HISTORY_FILE, autocomplete_button="tab")
|
||||
assert completer.history_filename == self.HISTORY_FILE
|
||||
assert completer.autocomplete_button == "tab"
|
||||
|
||||
def test_initial_setup_if_history_file_does_not_exist(self, fs, mock_readline):
|
||||
"""Tests initial setup creates history from commands when the history file is absent."""
|
||||
# Ensure the file does not exist in the fake filesystem.
|
||||
if os.path.exists(self.HISTORY_FILE):
|
||||
os.remove(self.HISTORY_FILE)
|
||||
|
||||
completer = AutoCompleter(history_filename=self.HISTORY_FILE)
|
||||
completer.initial_setup(self.COMMANDS)
|
||||
|
||||
mock_readline.read_history_file.assert_not_called()
|
||||
expected_calls = [call(cmd) for cmd in self.COMMANDS]
|
||||
mock_readline.add_history.assert_has_calls(expected_calls, any_order=True)
|
||||
assert mock_readline.add_history.call_count == len(self.COMMANDS)
|
||||
|
||||
mock_readline.set_completer.assert_called_with(completer._complete)
|
||||
mock_readline.parse_and_bind.assert_called_with("tab: complete")
|
||||
|
||||
def test_initial_setup_if_history_file_exists(self, fs, mock_readline):
|
||||
"""Tests initial setup reads from an existing history file."""
|
||||
fs.create_file(self.HISTORY_FILE, contents="previous_command\n")
|
||||
|
||||
completer = AutoCompleter(history_filename=self.HISTORY_FILE)
|
||||
completer.initial_setup(self.COMMANDS)
|
||||
|
||||
mock_readline.read_history_file.assert_called_once_with(self.HISTORY_FILE)
|
||||
mock_readline.add_history.assert_not_called()
|
||||
mock_readline.set_completer.assert_called_once()
|
||||
mock_readline.parse_and_bind.assert_called_once()
|
||||
|
||||
def test_initial_setup_with_no_history_filename(self, mock_readline):
|
||||
"""Tests initial setup when no history filename is provided."""
|
||||
completer = AutoCompleter(history_filename=None)
|
||||
completer.initial_setup(self.COMMANDS)
|
||||
|
||||
mock_readline.read_history_file.assert_not_called()
|
||||
expected_calls = [call(cmd) for cmd in self.COMMANDS]
|
||||
mock_readline.add_history.assert_has_calls(expected_calls, any_order=True)
|
||||
|
||||
def test_exit_setup_writes_and_filters_history(self, fs, mock_readline):
|
||||
"""Tests that exit_setup writes a filtered and unique history to the file."""
|
||||
# 1. Populate the mock readline history.
|
||||
mock_readline.add_history.side_effect(None) # Temporarily disable side effect to just record calls
|
||||
mock_readline.add_history("start server")
|
||||
mock_readline.add_history("stop client")
|
||||
mock_readline.add_history("invalid command")
|
||||
mock_readline.add_history("start server") # Add a duplicate.
|
||||
|
||||
# 2. Simulate the state of the history file after readline.write_history_file would have run.
|
||||
raw_history_content = "\n".join(["start server", "stop client", "invalid command", "start server"])
|
||||
fs.create_file(self.HISTORY_FILE, contents=raw_history_content)
|
||||
|
||||
# 3. Call the method under test.
|
||||
completer = AutoCompleter(history_filename=self.HISTORY_FILE)
|
||||
completer.exit_setup(all_commands=["start", "stop"], ignore_command_register=False)
|
||||
|
||||
# 4. Assert that readline's write function was called.
|
||||
mock_readline.write_history_file.assert_called_once_with(self.HISTORY_FILE)
|
||||
|
||||
# 5. Assert the file was correctly re-written with filtered and unique content.
|
||||
with open(self.HISTORY_FILE, "r") as f:
|
||||
content = f.read()
|
||||
lines = sorted(content.strip().split("\n"))
|
||||
assert lines == ["start server", "stop client"]
|
||||
|
||||
def test_exit_setup_with_no_history_filename(self, mock_readline):
|
||||
"""Tests that exit_setup does nothing if no filename is provided."""
|
||||
completer = AutoCompleter(history_filename=None)
|
||||
completer.exit_setup(all_commands=self.COMMANDS, ignore_command_register=False)
|
||||
mock_readline.write_history_file.assert_not_called()
|
||||
|
||||
def test_complete_with_no_matches(self, mock_readline):
|
||||
"""Tests the _complete method when there are no matching history items."""
|
||||
for cmd in ["start", "stop"]:
|
||||
mock_readline.add_history(cmd)
|
||||
|
||||
completer = AutoCompleter()
|
||||
assert completer._complete("run", 0) is None
|
||||
assert completer._complete("run", 1) is None
|
||||
|
||||
def test_complete_with_one_match(self, mock_readline):
|
||||
"""Tests the _complete method when there is exactly one match."""
|
||||
mock_readline.add_history("start server")
|
||||
mock_readline.add_history("stop server")
|
||||
|
||||
completer = AutoCompleter()
|
||||
assert completer._complete("start", 0) == "start server"
|
||||
assert completer._complete("start", 1) is None # Subsequent states yield no matches
|
||||
|
||||
def test_complete_with_multiple_matches(self, mock_readline):
|
||||
"""Tests _complete with multiple matches that share a common prefix."""
|
||||
mock_readline.add_history("status client")
|
||||
mock_readline.add_history("status server")
|
||||
mock_readline.add_history("stop")
|
||||
|
||||
completer = AutoCompleter()
|
||||
|
||||
# On state 0, it should insert the common prefix via readline and return None.
|
||||
result = completer._complete("stat", 0)
|
||||
assert result is None
|
||||
mock_readline.insert_text.assert_called_once_with("us ") # Completes "stat" to "status "
|
||||
mock_readline.redisplay.assert_called_once()
|
||||
|
||||
# On subsequent states, it should do nothing.
|
||||
mock_readline.reset_mock()
|
||||
result_state_1 = completer._complete("stat", 1)
|
||||
assert result_state_1 is None
|
||||
mock_readline.insert_text.assert_not_called()
|
||||
|
||||
|
||||
class TestHelperFunctions:
|
||||
"""Test suite for helper functions in the autocompleter module."""
|
||||
|
||||
def test_is_command_exist(self):
|
||||
"""Tests the _is_command_exist helper function."""
|
||||
existing = ["start", "stop", "status"]
|
||||
|
||||
# Case-sensitive check
|
||||
assert _is_command_exist("start", existing, ignore_command_register=False) is True
|
||||
assert _is_command_exist("START", existing, ignore_command_register=False) is False
|
||||
assert _is_command_exist("unknown", existing, ignore_command_register=False) is False
|
||||
|
||||
# Case-insensitive check
|
||||
assert _is_command_exist("start", existing, ignore_command_register=True) is True
|
||||
assert _is_command_exist("START", existing, ignore_command_register=True) is True
|
||||
assert _is_command_exist("unknown", existing, ignore_command_register=True) is False
|
||||
|
||||
def test_get_history_items(self, mock_readline):
|
||||
"""Tests the _get_history_items helper function."""
|
||||
assert _get_history_items() == []
|
||||
|
||||
mock_readline.add_history("first item")
|
||||
mock_readline.add_history("second item")
|
||||
|
||||
assert _get_history_items() == ["first item", "second item"]
|
||||
@@ -1,13 +1,13 @@
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from argenta.command.exceptions import (EmptyInputCommandException,
|
||||
RepeatedInputFlagsException,
|
||||
UnprocessedInputFlagException)
|
||||
from argenta.command.flag import Flag, InputFlag
|
||||
from argenta.command.flag.flags import Flags
|
||||
from argenta.command.flag.models import PossibleValues
|
||||
from argenta.command.models import InputCommand, Command, ValidationStatus
|
||||
from argenta.command.exceptions import (UnprocessedInputFlagException,
|
||||
RepeatedInputFlagsException,
|
||||
EmptyInputCommandException)
|
||||
|
||||
import unittest
|
||||
import re
|
||||
from argenta.command.flag.models import PossibleValues, ValidationStatus
|
||||
from argenta.command.models import Command, InputCommand
|
||||
|
||||
|
||||
class TestInputCommand(unittest.TestCase):
|
||||
@@ -26,25 +26,25 @@ class TestInputCommand(unittest.TestCase):
|
||||
with self.assertRaises(EmptyInputCommandException):
|
||||
InputCommand.parse('')
|
||||
|
||||
def test_validate_valid_input_flag1(self):
|
||||
def test_validate_invalid_input_flag1(self):
|
||||
command = Command('some', flags=Flag('test'))
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('test', input_value=None, status=None)), ValidationStatus.VALID)
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('test', input_value='', status=None)), ValidationStatus.INVALID)
|
||||
|
||||
def test_validate_valid_input_flag2(self):
|
||||
command = Command('some', flags=Flags([Flag('test'), Flag('more')]))
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('more', input_value=None, status=None)), ValidationStatus.VALID)
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('more', input_value='random-value', status=None)), ValidationStatus.VALID)
|
||||
|
||||
def test_validate_undefined_input_flag1(self):
|
||||
command = Command('some', flags=Flag('test'))
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('more', input_value=None, status=None)), ValidationStatus.UNDEFINED)
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('more', input_value='', status=None)), ValidationStatus.UNDEFINED)
|
||||
|
||||
def test_validate_undefined_input_flag2(self):
|
||||
command = Command('some', flags=Flags([Flag('test'), Flag('more')]))
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('case', input_value=None, status=None)), ValidationStatus.UNDEFINED)
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('case', input_value='', status=None)), ValidationStatus.UNDEFINED)
|
||||
|
||||
def test_validate_undefined_input_flag3(self):
|
||||
command = Command('some')
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('case', input_value=None, status=None)), ValidationStatus.UNDEFINED)
|
||||
self.assertEqual(command.validate_input_flag(InputFlag('case', input_value='', status=None)), ValidationStatus.UNDEFINED)
|
||||
|
||||
def test_invalid_input_flag1(self):
|
||||
command = Command('some', flags=Flag('test', possible_values=PossibleValues.NEITHER))
|
||||
@@ -61,4 +61,3 @@ class TestInputCommand(unittest.TestCase):
|
||||
def test_isinstance_parse_correct_raw_command(self):
|
||||
cmd = InputCommand.parse('ssh --host 192.168.0.3')
|
||||
self.assertIsInstance(cmd, InputCommand)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from argenta.app.dividing_line import DynamicDividingLine, StaticDividingLine
|
||||
|
||||
import unittest
|
||||
|
||||
from argenta.app.dividing_line import DynamicDividingLine, StaticDividingLine
|
||||
|
||||
|
||||
class TestDividingLine(unittest.TestCase):
|
||||
def test_get_static_dividing_line_full_line(self):
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from argenta.command.flag import Flag, InputFlag, PossibleValues
|
||||
from argenta.command.flag.flags import InputFlags, Flags
|
||||
|
||||
import unittest
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from argenta.command.flag import Flag, InputFlag, PossibleValues
|
||||
from argenta.command.flag.flags import Flags, InputFlags
|
||||
|
||||
|
||||
class TestFlag(unittest.TestCase):
|
||||
@@ -29,8 +29,8 @@ class TestFlag(unittest.TestCase):
|
||||
'--')
|
||||
|
||||
def test_get_flag_value_without_set(self):
|
||||
self.assertEqual(InputFlag(name='test', input_value=None, status=None).input_value,
|
||||
None)
|
||||
self.assertEqual(InputFlag(name='test', input_value='', status=None).input_value,
|
||||
'')
|
||||
|
||||
def test_get_flag_value_with_set(self):
|
||||
flag = InputFlag(name='test', input_value='example', status=None)
|
||||
@@ -54,11 +54,11 @@ class TestFlag(unittest.TestCase):
|
||||
|
||||
def test_validate_correct_empty_flag_value_without_possible_flag_values(self):
|
||||
flag = Flag(name='test', possible_values=PossibleValues.NEITHER)
|
||||
self.assertEqual(flag.validate_input_flag_value(None), True)
|
||||
self.assertEqual(flag.validate_input_flag_value(''), True)
|
||||
|
||||
def test_validate_correct_empty_flag_value_with_possible_flag_values(self):
|
||||
flag = Flag(name='test', possible_values=PossibleValues.NEITHER)
|
||||
self.assertEqual(flag.validate_input_flag_value(None), True)
|
||||
self.assertEqual(flag.validate_input_flag_value(''), True)
|
||||
|
||||
def test_validate_incorrect_random_flag_value_without_possible_flag_values(self):
|
||||
flag = Flag(name='test', possible_values=PossibleValues.NEITHER)
|
||||
@@ -69,19 +69,19 @@ class TestFlag(unittest.TestCase):
|
||||
self.assertEqual(flag.validate_input_flag_value('random value'), True)
|
||||
|
||||
def test_get_input_flag1(self):
|
||||
flag = InputFlag(name='test', input_value=None, status=None)
|
||||
flag = InputFlag(name='test', input_value='', status=None)
|
||||
input_flags = InputFlags([flag])
|
||||
self.assertEqual(input_flags.get_flag_by_name('test'), flag)
|
||||
|
||||
def test_get_input_flag2(self):
|
||||
flag = InputFlag(name='test', input_value=None, status=None)
|
||||
flag2 = InputFlag(name='some', input_value=None, status=None)
|
||||
flag = InputFlag(name='test', input_value='', status=None)
|
||||
flag2 = InputFlag(name='some', input_value='', status=None)
|
||||
input_flags = InputFlags([flag, flag2])
|
||||
self.assertEqual(input_flags.get_flag_by_name('some'), flag2)
|
||||
|
||||
def test_get_undefined_input_flag(self):
|
||||
flag = InputFlag(name='test', input_value=None, status=None)
|
||||
flag2 = InputFlag(name='some', input_value=None, status=None)
|
||||
flag = InputFlag(name='test', input_value='', status=None)
|
||||
flag2 = InputFlag(name='some', input_value='', status=None)
|
||||
input_flags = InputFlags([flag, flag2])
|
||||
self.assertEqual(input_flags.get_flag_by_name('case'), None)
|
||||
|
||||
|
||||
@@ -1,131 +1,80 @@
|
||||
import unittest
|
||||
from datetime import datetime, date
|
||||
from datetime import date, datetime
|
||||
|
||||
from argenta.response.entity import Response, DataBridge, EMPTY_INPUT_FLAGS
|
||||
from argenta.response.status import ResponseStatus
|
||||
from argenta.data_bridge import DataBridge
|
||||
from argenta.command.flag.models import InputFlag
|
||||
from argenta.command.flag.flags.models import InputFlags
|
||||
from argenta.command.flag import InputFlag
|
||||
from argenta.response.entity import EMPTY_INPUT_FLAGS, Response
|
||||
from argenta.response.status import ResponseStatus
|
||||
|
||||
|
||||
class TestDataBridge(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Clear data before each test"""
|
||||
DataBridge.clear_data()
|
||||
|
||||
def tearDown(self):
|
||||
"""Clear data after each test"""
|
||||
DataBridge.clear_data()
|
||||
"""Create a new DataBridge instance for each test"""
|
||||
self.data_bridge = DataBridge()
|
||||
|
||||
def test_update_data_basic(self):
|
||||
"""Test basic data update functionality"""
|
||||
test_data = {"key1": "value1", "key2": "value2"}
|
||||
DataBridge.update_data(test_data)
|
||||
self.assertEqual(DataBridge.get_data(), test_data)
|
||||
self.data_bridge.update(test_data)
|
||||
self.assertEqual(self.data_bridge.get_all(), test_data)
|
||||
|
||||
def test_update_data_with_datetime(self):
|
||||
"""Test updating data with datetime objects"""
|
||||
test_datetime = datetime(2024, 1, 15, 10, 30, 45)
|
||||
test_data = {"created_at": test_datetime, "name": "test"}
|
||||
DataBridge.update_data(test_data)
|
||||
|
||||
result = DataBridge.get_data()
|
||||
self.data_bridge.update(test_data)
|
||||
|
||||
result = self.data_bridge.get_all()
|
||||
self.assertEqual(result["created_at"], test_datetime)
|
||||
self.assertEqual(result["name"], "test")
|
||||
|
||||
def test_update_data_with_date(self):
|
||||
"""Test updating data with date objects"""
|
||||
test_date = date(2024, 1, 15)
|
||||
test_data = {"birth_date": test_date, "active": True}
|
||||
DataBridge.update_data(test_data)
|
||||
|
||||
result = DataBridge.get_data()
|
||||
self.assertEqual(result["birth_date"], test_date)
|
||||
self.assertEqual(result["active"], True)
|
||||
|
||||
def test_update_data_multiple_calls(self):
|
||||
"""Test multiple update_data calls merge data"""
|
||||
first_data = {"key1": "value1", "date1": date(2024, 1, 1)}
|
||||
second_data = {"key2": "value2", "date2": datetime(2024, 2, 1, 12, 0)}
|
||||
|
||||
DataBridge.update_data(first_data)
|
||||
DataBridge.update_data(second_data)
|
||||
|
||||
result = DataBridge.get_data()
|
||||
self.assertEqual(len(result), 4)
|
||||
self.assertEqual(result["key1"], "value1")
|
||||
self.assertEqual(result["key2"], "value2")
|
||||
self.assertEqual(result["date1"], date(2024, 1, 1))
|
||||
self.assertEqual(result["date2"], datetime(2024, 2, 1, 12, 0))
|
||||
|
||||
def test_update_data_overwrites_existing_keys(self):
|
||||
"""Test that update_data overwrites existing keys"""
|
||||
initial_data = {"key": "old_value", "date": date(2024, 1, 1)}
|
||||
updated_data = {"key": "new_value", "date": date(2024, 2, 1)}
|
||||
|
||||
DataBridge.update_data(initial_data)
|
||||
DataBridge.update_data(updated_data)
|
||||
|
||||
result = DataBridge.get_data()
|
||||
self.assertEqual(result["key"], "new_value")
|
||||
self.assertEqual(result["date"], date(2024, 2, 1))
|
||||
"""Test multiple update calls merge data"""
|
||||
first_data = {"key1": "value1"}
|
||||
second_data = {"key2": "value2"}
|
||||
self.data_bridge.update(first_data)
|
||||
self.data_bridge.update(second_data)
|
||||
self.assertEqual(len(self.data_bridge.get_all()), 2)
|
||||
|
||||
def test_get_data_empty(self):
|
||||
"""Test get_data returns empty dict when no data"""
|
||||
result = DataBridge.get_data()
|
||||
self.assertEqual(result, {})
|
||||
"""Test get_all returns empty dict when no data"""
|
||||
self.assertEqual(self.data_bridge.get_all(), {})
|
||||
|
||||
def test_clear_data(self):
|
||||
"""Test clear_data removes all data"""
|
||||
test_data = {"key": "value", "timestamp": datetime.now()}
|
||||
DataBridge.update_data(test_data)
|
||||
|
||||
# Verify data exists
|
||||
self.assertNotEqual(DataBridge.get_data(), {})
|
||||
|
||||
# Clear and verify
|
||||
DataBridge.clear_data()
|
||||
self.assertEqual(DataBridge.get_data(), {})
|
||||
"""Test clear_all removes all data"""
|
||||
self.data_bridge.update({"key": "value"})
|
||||
self.assertNotEqual(self.data_bridge.get_all(), {})
|
||||
self.data_bridge.clear_all()
|
||||
self.assertEqual(self.data_bridge.get_all(), {})
|
||||
|
||||
def test_delete_from_data(self):
|
||||
"""Test delete_from_data removes specific key"""
|
||||
test_data = {
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"created_at": datetime(2024, 1, 1, 10, 0)
|
||||
}
|
||||
DataBridge.update_data(test_data)
|
||||
|
||||
# Delete one key
|
||||
DataBridge.delete_from_data("key1")
|
||||
|
||||
result = DataBridge.get_data()
|
||||
self.assertEqual(len(result), 2)
|
||||
"""Test delete_by_key removes specific key"""
|
||||
test_data = {"key1": "value1", "key2": "value2"}
|
||||
self.data_bridge.update(test_data)
|
||||
self.data_bridge.delete_by_key("key1")
|
||||
result = self.data_bridge.get_all()
|
||||
self.assertNotIn("key1", result)
|
||||
self.assertIn("key2", result)
|
||||
self.assertIn("created_at", result)
|
||||
|
||||
def test_delete_from_data_nonexistent_key(self):
|
||||
"""Test delete_from_data with nonexistent key raises KeyError"""
|
||||
test_data = {"existing_key": "value"}
|
||||
DataBridge.update_data(test_data)
|
||||
|
||||
"""Test delete_by_key with nonexistent key raises KeyError"""
|
||||
with self.assertRaises(KeyError):
|
||||
DataBridge.delete_from_data("nonexistent_key")
|
||||
self.data_bridge.delete_by_key("nonexistent_key")
|
||||
|
||||
def test_get_by_key(self):
|
||||
"""Test get_by_key retrieves correct value"""
|
||||
test_data = {"key1": "value1", "key2": date(2024, 1, 1)}
|
||||
self.data_bridge.update(test_data)
|
||||
self.assertEqual(self.data_bridge.get_by_key("key1"), "value1")
|
||||
self.assertEqual(self.data_bridge.get_by_key("key2"), date(2024, 1, 1))
|
||||
self.assertIsNone(self.data_bridge.get_by_key("nonexistent"))
|
||||
|
||||
|
||||
class TestResponse(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Clear data before each test"""
|
||||
DataBridge.clear_data()
|
||||
|
||||
def tearDown(self):
|
||||
"""Clear data after each test"""
|
||||
DataBridge.clear_data()
|
||||
|
||||
def test_response_initialization_basic(self):
|
||||
"""Test basic Response initialization"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
|
||||
self.assertEqual(response.status, ResponseStatus.ALL_FLAGS_VALID)
|
||||
self.assertEqual(response.input_flags, EMPTY_INPUT_FLAGS)
|
||||
|
||||
@@ -133,151 +82,9 @@ class TestResponse(unittest.TestCase):
|
||||
"""Test Response initialization with input flags"""
|
||||
input_flags = InputFlags([InputFlag('test', input_value='value', status=None)])
|
||||
response = Response(ResponseStatus.INVALID_VALUE_FLAGS, input_flags)
|
||||
|
||||
self.assertEqual(response.status, ResponseStatus.INVALID_VALUE_FLAGS)
|
||||
self.assertEqual(response.input_flags, input_flags)
|
||||
|
||||
def test_response_inherits_databridge_functionality(self):
|
||||
"""Test that Response inherits DataBridge methods"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
test_data = {"message": "hello", "timestamp": datetime.now()}
|
||||
|
||||
# Test update_data
|
||||
response.update_data(test_data)
|
||||
result = response.get_data()
|
||||
self.assertEqual(result["message"], "hello")
|
||||
self.assertIsInstance(result["timestamp"], datetime)
|
||||
|
||||
def test_response_data_passing_with_dates(self):
|
||||
"""Test passing date and datetime objects through Response"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
|
||||
current_time = datetime.now()
|
||||
today = date.today()
|
||||
|
||||
date_data = {
|
||||
"current_datetime": current_time,
|
||||
"current_date": today,
|
||||
"custom_datetime": datetime(2024, 3, 15, 14, 30, 0),
|
||||
"custom_date": date(2023, 12, 25),
|
||||
"metadata": {"created": current_time, "updated": today}
|
||||
}
|
||||
|
||||
response.update_data(date_data)
|
||||
retrieved_data = response.get_data()
|
||||
|
||||
# Verify datetime objects are preserved
|
||||
self.assertEqual(retrieved_data["current_datetime"], current_time)
|
||||
self.assertEqual(retrieved_data["current_date"], today)
|
||||
self.assertEqual(retrieved_data["custom_datetime"], datetime(2024, 3, 15, 14, 30, 0))
|
||||
self.assertEqual(retrieved_data["custom_date"], date(2023, 12, 25))
|
||||
|
||||
# Verify nested datetime objects
|
||||
self.assertEqual(retrieved_data["metadata"]["created"], current_time)
|
||||
self.assertEqual(retrieved_data["metadata"]["updated"], today)
|
||||
|
||||
def test_response_data_persistence_across_instances(self):
|
||||
"""Test that data persists across different Response instances"""
|
||||
# First response instance
|
||||
response1 = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
test_datetime = datetime(2024, 1, 1, 12, 0, 0)
|
||||
response1.update_data({"session_start": test_datetime})
|
||||
|
||||
# Second response instance
|
||||
response2 = Response(ResponseStatus.UNDEFINED_FLAGS)
|
||||
retrieved_data = response2.get_data()
|
||||
|
||||
# Data should persist
|
||||
self.assertEqual(retrieved_data["session_start"], test_datetime)
|
||||
|
||||
def test_response_data_complex_date_scenarios(self):
|
||||
"""Test complex scenarios with date/datetime handling"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
|
||||
# Create complex data structure with various date formats
|
||||
complex_data = {
|
||||
"user": {
|
||||
"name": "John Doe",
|
||||
"birth_date": date(1990, 5, 15),
|
||||
"last_login": datetime(2024, 1, 15, 10, 30, 45),
|
||||
"preferences": {
|
||||
"timezone": "UTC",
|
||||
"date_format": "%Y-%m-%d",
|
||||
"created_at": datetime(2023, 1, 1, 0, 0, 0)
|
||||
}
|
||||
},
|
||||
"events": [
|
||||
{"name": "login", "timestamp": datetime(2024, 1, 15, 10, 30, 45)},
|
||||
{"name": "logout", "timestamp": datetime(2024, 1, 15, 18, 45, 30)},
|
||||
],
|
||||
"dates_list": [
|
||||
date(2024, 1, 1),
|
||||
date(2024, 1, 2),
|
||||
date(2024, 1, 3)
|
||||
]
|
||||
}
|
||||
|
||||
response.update_data(complex_data)
|
||||
retrieved_data = response.get_data()
|
||||
|
||||
# Verify all date/datetime objects are correctly preserved
|
||||
self.assertEqual(retrieved_data["user"]["birth_date"], date(1990, 5, 15))
|
||||
self.assertEqual(retrieved_data["user"]["last_login"], datetime(2024, 1, 15, 10, 30, 45))
|
||||
self.assertEqual(retrieved_data["user"]["preferences"]["created_at"], datetime(2023, 1, 1, 0, 0, 0))
|
||||
|
||||
# Verify dates in lists
|
||||
self.assertEqual(len(retrieved_data["events"]), 2)
|
||||
self.assertEqual(retrieved_data["events"][0]["timestamp"], datetime(2024, 1, 15, 10, 30, 45))
|
||||
self.assertEqual(retrieved_data["events"][1]["timestamp"], datetime(2024, 1, 15, 18, 45, 30))
|
||||
|
||||
# Verify date list
|
||||
self.assertEqual(len(retrieved_data["dates_list"]), 3)
|
||||
self.assertEqual(retrieved_data["dates_list"][0], date(2024, 1, 1))
|
||||
self.assertEqual(retrieved_data["dates_list"][1], date(2024, 1, 2))
|
||||
self.assertEqual(retrieved_data["dates_list"][2], date(2024, 1, 3))
|
||||
|
||||
def test_response_clear_data_functionality(self):
|
||||
"""Test clearing data functionality through Response"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
|
||||
# Add some data with dates
|
||||
response.update_data({
|
||||
"timestamp": datetime.now(),
|
||||
"date": date.today(),
|
||||
"message": "test"
|
||||
})
|
||||
|
||||
# Verify data exists
|
||||
self.assertNotEqual(response.get_data(), {})
|
||||
|
||||
# Clear data
|
||||
response.clear_data()
|
||||
|
||||
# Verify data is cleared
|
||||
self.assertEqual(response.get_data(), {})
|
||||
|
||||
def test_response_delete_specific_date_data(self):
|
||||
"""Test deleting specific date-related data"""
|
||||
response = Response(ResponseStatus.ALL_FLAGS_VALID)
|
||||
|
||||
# Add mixed data
|
||||
test_data = {
|
||||
"start_date": date(2024, 1, 1),
|
||||
"end_date": date(2024, 12, 31),
|
||||
"created_at": datetime.now(),
|
||||
"name": "test_session"
|
||||
}
|
||||
response.update_data(test_data)
|
||||
|
||||
# Delete specific date field
|
||||
response.delete_from_data("start_date")
|
||||
|
||||
result = response.get_data()
|
||||
self.assertNotIn("start_date", result)
|
||||
self.assertIn("end_date", result)
|
||||
self.assertIn("created_at", result)
|
||||
self.assertIn("name", result)
|
||||
|
||||
def test_response_status_types(self):
|
||||
"""Test Response with different status types"""
|
||||
statuses = [
|
||||
@@ -286,14 +93,10 @@ class TestResponse(unittest.TestCase):
|
||||
ResponseStatus.INVALID_VALUE_FLAGS,
|
||||
ResponseStatus.UNDEFINED_AND_INVALID_FLAGS
|
||||
]
|
||||
|
||||
for status in statuses:
|
||||
response = Response(status)
|
||||
response.update_data({"timestamp": datetime.now(), "status_test": True})
|
||||
|
||||
self.assertEqual(response.status, status)
|
||||
self.assertIn("timestamp", response.get_data())
|
||||
self.assertIn("status_test", response.get_data())
|
||||
with self.subTest(status=status):
|
||||
response = Response(status)
|
||||
self.assertEqual(response.status, status)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from argenta.command.flag import InputFlag, Flag
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from argenta.command import Command
|
||||
from argenta.command.flag import Flag, InputFlag
|
||||
from argenta.command.flag.flags import Flags, InputFlags
|
||||
from argenta.command.flag.models import PossibleValues, ValidationStatus
|
||||
from argenta.response.entity import Response
|
||||
from argenta.router import Router
|
||||
from argenta.command import Command
|
||||
from argenta.router.entity import _structuring_input_flags, _validate_command, _validate_func_args # pyright: ignore[reportPrivateUsage]
|
||||
from argenta.router.exceptions import (TriggerContainSpacesException,
|
||||
RepeatedFlagNameException,
|
||||
RequiredArgumentNotPassedException)
|
||||
|
||||
import unittest
|
||||
import re
|
||||
from argenta.router.entity import _structuring_input_flags, _validate_command, _validate_func_args # pyright: ignore[reportPrivateUsage]
|
||||
from argenta.router.exceptions import (RepeatedFlagNameException,
|
||||
RequiredArgumentNotPassedException,
|
||||
TriggerContainSpacesException)
|
||||
|
||||
|
||||
class TestRouter(unittest.TestCase):
|
||||
|
||||
Reference in New Issue
Block a user