mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-06-09 08:11:50 +00:00
test: add unit tests for AutoInterface bind-failure detection and user guidance messages
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# SPDX-License-Identifier: 0BSD
|
||||
|
||||
"""Tests for AutoInterface bind-failure detection in user guidance.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from meshchatx.meshchat import ReticulumMeshChat
|
||||
|
||||
|
||||
def _make_app(config_interfaces):
|
||||
"""Build a minimal app stub exposing only what the helpers touch."""
|
||||
app = SimpleNamespace()
|
||||
app.reticulum = SimpleNamespace(
|
||||
config={"interfaces": dict(config_interfaces)},
|
||||
transport_enabled=lambda: True,
|
||||
)
|
||||
app._get_interfaces_section = (
|
||||
ReticulumMeshChat._get_interfaces_section.__get__(app)
|
||||
)
|
||||
app._detect_failed_autointerfaces = (
|
||||
ReticulumMeshChat._detect_failed_autointerfaces.__get__(app)
|
||||
)
|
||||
return app
|
||||
|
||||
|
||||
class _FakeAutoInterface:
|
||||
pass
|
||||
|
||||
|
||||
_FakeAutoInterface.__name__ = "AutoInterface"
|
||||
|
||||
|
||||
class _FakeTCPClientInterface:
|
||||
pass
|
||||
|
||||
|
||||
_FakeTCPClientInterface.__name__ = "TCPClientInterface"
|
||||
|
||||
|
||||
def test_detects_enabled_autointerface_that_failed_to_start():
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {"type": "AutoInterface", "enabled": "yes"},
|
||||
},
|
||||
)
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = []
|
||||
assert app._detect_failed_autointerfaces() == ["Default Interface"]
|
||||
|
||||
|
||||
def test_running_autointerface_is_not_reported():
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {"type": "AutoInterface", "enabled": "yes"},
|
||||
},
|
||||
)
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = [_FakeAutoInterface()]
|
||||
assert app._detect_failed_autointerfaces() == []
|
||||
|
||||
|
||||
def test_disabled_autointerface_is_ignored():
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {"type": "AutoInterface", "enabled": "no"},
|
||||
},
|
||||
)
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = []
|
||||
assert app._detect_failed_autointerfaces() == []
|
||||
|
||||
|
||||
def test_non_auto_interface_does_not_trigger_warning():
|
||||
app = _make_app(
|
||||
{
|
||||
"Hub": {
|
||||
"type": "TCPClientInterface",
|
||||
"enabled": "yes",
|
||||
"target_host": "127.0.0.1",
|
||||
"target_port": "4242",
|
||||
},
|
||||
},
|
||||
)
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = [_FakeTCPClientInterface()]
|
||||
assert app._detect_failed_autointerfaces() == []
|
||||
|
||||
|
||||
def test_empty_interfaces_section_is_safe():
|
||||
app = _make_app({})
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = []
|
||||
assert app._detect_failed_autointerfaces() == []
|
||||
|
||||
|
||||
def test_guidance_message_emitted_for_failed_autointerface():
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {"type": "AutoInterface", "enabled": "yes"},
|
||||
},
|
||||
)
|
||||
app.config = MagicMock()
|
||||
app.config.auto_announce_enabled.get.return_value = True
|
||||
app.build_user_guidance_messages = (
|
||||
ReticulumMeshChat.build_user_guidance_messages.__get__(app)
|
||||
)
|
||||
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = []
|
||||
guidance = app.build_user_guidance_messages()
|
||||
|
||||
autointerface_msgs = [g for g in guidance if g["id"] == "autointerface_bind_failed"]
|
||||
assert len(autointerface_msgs) == 1
|
||||
msg = autointerface_msgs[0]
|
||||
assert msg["severity"] == "warning"
|
||||
assert msg["action_route"] == "/interfaces"
|
||||
assert "Default Interface" in msg["description"]
|
||||
assert "Sideband" in msg["description"]
|
||||
|
||||
|
||||
def test_guidance_message_absent_when_autointerface_running():
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {"type": "AutoInterface", "enabled": "yes"},
|
||||
},
|
||||
)
|
||||
app.config = MagicMock()
|
||||
app.config.auto_announce_enabled.get.return_value = True
|
||||
app.build_user_guidance_messages = (
|
||||
ReticulumMeshChat.build_user_guidance_messages.__get__(app)
|
||||
)
|
||||
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = [_FakeAutoInterface()]
|
||||
guidance = app.build_user_guidance_messages()
|
||||
|
||||
assert not any(g["id"] == "autointerface_bind_failed" for g in guidance)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enabled_value", ["yes", "true", "1", "Yes", "TRUE"])
|
||||
def test_truthy_enabled_values_are_recognised(enabled_value):
|
||||
app = _make_app(
|
||||
{
|
||||
"Default Interface": {
|
||||
"type": "AutoInterface",
|
||||
"enabled": enabled_value,
|
||||
},
|
||||
},
|
||||
)
|
||||
with patch("meshchatx.meshchat.RNS.Transport") as transport:
|
||||
transport.interfaces = []
|
||||
assert app._detect_failed_autointerfaces() == ["Default Interface"]
|
||||
Reference in New Issue
Block a user