mirror of
https://github.com/pdxlocations/contact.git
synced 2026-10-31 00:01:57 +01:00
- Consolidated command-line argument parsing and handling into a unified structure. - Introduced a new runtime module to manage the main application logic. - Updated settings management to streamline the user experience and improve error handling. - Enhanced versioning and help display functionality across the application. - Refactored UI components to ensure compatibility with the new command structure. - Added comprehensive tests for CLI functionality and settings management.
64 lines
3.0 KiB
Python
64 lines
3.0 KiB
Python
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from types import SimpleNamespace
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
import contact.__main__ as cli
|
|
import contact.settings as settings_cli
|
|
from contact.version import __version__
|
|
|
|
|
|
class CliTests(unittest.TestCase):
|
|
def test_help_version_and_errors_work_without_runtime_configuration(self) -> None:
|
|
cases = [
|
|
(["--help"], 0, "usage:"),
|
|
(["-h"], 0, "usage:"),
|
|
(["--version"], 0, __version__),
|
|
(["-V"], 0, __version__),
|
|
(["--unknown"], 2, "unrecognized arguments"),
|
|
(["--host", "localhost", "--ble"], 2, "not allowed with argument"),
|
|
(["--", "--version"], 2, "unrecognized arguments"),
|
|
]
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
config_root = Path(directory) / "missing"
|
|
env = dict(os.environ, CONTACT_CONFIG_ROOT=str(config_root))
|
|
for command in (["-m", "contact"], ["-m", "contact.settings"],
|
|
["-c", "from contact.__main__ import start; start()"]):
|
|
for flags, code, expected in cases:
|
|
with self.subTest(command=command, flags=flags):
|
|
result = subprocess.run(
|
|
[sys.executable, *command, *flags], env=env,
|
|
capture_output=True, text=True, timeout=10,
|
|
)
|
|
self.assertEqual(result.returncode, code, result.stderr)
|
|
self.assertIn(expected, result.stderr if code else result.stdout)
|
|
self.assertEqual(result.stdout if code else result.stderr, "")
|
|
self.assertFalse(config_root.exists())
|
|
|
|
def test_control_aliases_preserve_connection_options(self) -> None:
|
|
for alias in ("--settings", "--set", "--control", "-c"):
|
|
for connection, value, attribute in (
|
|
("--host", "mesh.local", "host"),
|
|
("--port", "/dev/ttyUSB0", "port"),
|
|
("--ble", "my-radio", "ble"),
|
|
):
|
|
with self.subTest(alias=alias, connection=connection):
|
|
runtime = SimpleNamespace(start=mock.Mock())
|
|
with mock.patch.dict(sys.modules, {"contact.settings_runtime": runtime}):
|
|
cli.start([alias, connection, value])
|
|
runtime.start.assert_called_once()
|
|
self.assertEqual(getattr(runtime.start.call_args.args[0], attribute), value)
|
|
|
|
def test_main_and_standalone_settings_pass_parsed_options(self) -> None:
|
|
for entrypoint, module in ((cli, "contact.runtime"),
|
|
(settings_cli, "contact.settings_runtime")):
|
|
runtime = SimpleNamespace(start=mock.Mock())
|
|
with mock.patch.dict(sys.modules, {module: runtime}):
|
|
entrypoint.start(["--host=mesh.local"])
|
|
runtime.start.assert_called_once()
|
|
self.assertEqual(runtime.start.call_args.args[0].host, "mesh.local")
|