summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-22 16:40:54 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-22 16:40:54 +0200
commit9c136a0e37add42f5d0c8675a797969cfe690de0 (patch)
treed5dfd3a7e2289a769dc987f086eec3f475054f85 /packages/meshbay-node/tests
parent2dbd70484e65ae57e18c323381136077cd00adad (diff)
downloadmeshbay-9c136a0e37add42f5d0c8675a797969cfe690de0.tar.gz
fix: first-run wizard reliability and node startup performance
Node daemon no longer blocks startup on slow directory scans — initial indexing runs in the background so the node reaches "running" immediately after transports are up. Fixes the wizard failing to detect the node when large USB/NAS roots take minutes to scan. Also: wizard key-linking deadlock resolved (main.js links during poll), invite form stays in DOM during reconnects (disabled instead of destroyed), pairing code bridges to renderer, and firewall docs for LAN casting added. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests')
-rw-r--r--packages/meshbay-node/tests/test_daemon.py46
-rw-r--r--packages/meshbay-node/tests/test_security_regressions.py2
2 files changed, 34 insertions, 14 deletions
diff --git a/packages/meshbay-node/tests/test_daemon.py b/packages/meshbay-node/tests/test_daemon.py
index 7974be5..ab1613d 100644
--- a/packages/meshbay-node/tests/test_daemon.py
+++ b/packages/meshbay-node/tests/test_daemon.py
@@ -160,11 +160,11 @@ async def test_daemon_creates_chat_store(tmp_path, node_config, gek, hub_pk_pem)
assert store._db is None
@pytest.mark.asyncio
-async def test_daemon_no_groups_exits(tmp_path):
- """Daemon with no valid groups exits cleanly."""
+async def test_daemon_no_groups_stays_up(tmp_path, hub_pk_pem):
+ """Daemon with no valid groups stays up (admin UI + hub connection alive)."""
config = Config(
hub=HubConfig(url="http://localhost:9999", username="testuser"),
- node=NodeConfig(),
+ node=NodeConfig(quic_port=_free_port(), ui_port=_free_port()),
groups=[GroupConfig(id="", name="empty", shared_dir="")],
keystore=KeystoreConfig(path=tmp_path / "keystore.enc"),
data_dir=tmp_path / "data",
@@ -177,28 +177,48 @@ async def test_daemon_no_groups_exits(tmp_path):
mock_session = MagicMock()
mock_session.node_id = "node123"
mock_session.user_id = "user123"
- mock_session.hub_pk_pem = b"pem"
+ mock_session.hub_pk_pem = hub_pk_pem
- mock_server = AsyncMock()
- mock_server.serve = AsyncMock()
+ shutdown_event = asyncio.Event()
with patch("meshbay_node.daemon.load_or_create_keystore", return_value=mock_keys), \
- patch("meshbay_node.daemon.HubClient") as MockHub, \
- patch("meshbay_node.daemon.uvicorn") as mock_uvicorn:
-
- mock_uvicorn.Config = MagicMock()
- mock_uvicorn.Server = MagicMock(return_value=mock_server)
+ patch("meshbay_node.daemon.HubClient") as MockHub:
hub_instance = AsyncMock()
hub_instance.startup = AsyncMock(return_value=mock_session)
+ hub_instance.send_ws = AsyncMock()
+ hub_instance._ws = None
hub_instance.close = AsyncMock()
hub_instance.__aenter__ = AsyncMock(return_value=hub_instance)
hub_instance.__aexit__ = AsyncMock(return_value=False)
MockHub.return_value = hub_instance
- await daemon.run()
+ async def mock_maintain_ws(**kwargs):
+ await shutdown_event.wait()
+
+ hub_instance.maintain_ws = mock_maintain_ws
- assert len(daemon._chat_stores) == 0
+ async def run_daemon():
+ with patch("signal.SIGINT", 2), \
+ patch("signal.SIGTERM", 15):
+ try:
+ await asyncio.wait_for(daemon.run(), timeout=5)
+ except (asyncio.TimeoutError, Exception):
+ pass
+
+ task = asyncio.create_task(run_daemon())
+ await asyncio.sleep(1)
+
+ assert daemon._state["status"] == "running"
+ assert len(daemon._chat_stores) == 0
+
+ shutdown_event.set()
+ await daemon._shutdown()
+ task.cancel()
+ try:
+ await task
+ except (asyncio.CancelledError, Exception):
+ pass
@pytest.mark.asyncio
async def test_daemon_index_change_pushes_to_peers(tmp_path, shared_dir, gek, hub_pk_pem):
diff --git a/packages/meshbay-node/tests/test_security_regressions.py b/packages/meshbay-node/tests/test_security_regressions.py
index 78a631a..725b800 100644
--- a/packages/meshbay-node/tests/test_security_regressions.py
+++ b/packages/meshbay-node/tests/test_security_regressions.py
@@ -488,7 +488,7 @@ def test_swarm_registration_skips_private_groups():
/ "daemon.py").read_text()
assert 'visibility' in source and '_register_swarm' in source
# Both registration sites must gate on public visibility.
- for marker in ['gctx.get("visibility") != "public"',
+ for marker in ['gctx.get("visibility") == "public"',
'group_cfg.visibility == "public"']:
assert marker in source, f"swarm registration not gated: {marker}"