"""Nexus — Step 0: Infrastructure Tests (R8: Redis + WebSocket + Session leak) Tests: - R8: Redis BlockingConnectionPool configuration - R8: WebSocket ConnectionManager - D7: DB Session middleware """ import pytest import asyncio from unittest.mock import AsyncMock, MagicMock, patch class TestRedisClient: """R8: Redis client tests""" def test_get_redis_raises_before_init(self): """get_redis() raises RuntimeError if called before init_redis()""" from server.infrastructure.redis.client import get_redis # Reset module state import server.infrastructure.redis.client as redis_mod redis_mod._redis = None with pytest.raises(RuntimeError, match="Redis not initialized"): get_redis() def test_get_redis_sync_returns_none_before_init(self): """get_redis_sync() returns None if Redis not initialized""" import server.infrastructure.redis.client as redis_mod redis_mod._redis = None from server.infrastructure.redis.client import get_redis_sync assert get_redis_sync() is None @pytest.mark.asyncio async def test_init_redis_exits_on_empty_url(self): """init_redis() raises SystemExit if REDIS_URL is empty""" from server.infrastructure.redis.client import init_redis import server.config as config_mod original_url = config_mod.settings.REDIS_URL config_mod.settings.REDIS_URL = "" with pytest.raises(SystemExit, match="REDIS_URL must be set"): await init_redis(MagicMock()) config_mod.settings.REDIS_URL = original_url class TestWebSocketManager: """R8: WebSocket ConnectionManager tests""" def test_manager_initial_state(self): """ConnectionManager starts with zero connections""" from server.api.websocket import ConnectionManager manager = ConnectionManager() assert manager.client_count == 0 def test_manager_disconnect_nonexistent(self): """Disconnecting a non-existent client is a no-op""" from server.api.websocket import ConnectionManager manager = ConnectionManager() manager.disconnect("nonexistent") # Should not raise assert manager.client_count == 0 def test_manager_update_pong(self): """update_pong updates last_pong_time for existing connection""" from server.api.websocket import ConnectionManager import time manager = ConnectionManager() ws_mock = MagicMock() manager._connections["test_client"] = { "websocket": ws_mock, "last_pong": time.monotonic() - 10, } before = manager._connections["test_client"]["last_pong"] manager.update_pong("test_client") after = manager._connections["test_client"]["last_pong"] assert after > before class TestDbSessionMiddleware: """D7: DB Session middleware tests""" @pytest.mark.asyncio async def test_middleware_skips_non_api_routes(self): """Middleware skips non-API routes (WebSocket, health, static)""" from server.main import DbSessionMiddleware from starlette.responses import Response inner = AsyncMock() middleware = DbSessionMiddleware(app=inner) # Create a proper ASGI scope for a non-API path scope = { "type": "http", "method": "GET", "path": "/favicon.ico", "query_string": b"", "headers": [], } async def receive(): return {"type": "http.request", "body": b"", "more_body": False} sent = [] async def send(message): sent.append(message) await middleware(scope, receive, send) inner.assert_called_once() class TestJWTAuth: """A5: JWT authentication tests""" def test_public_path_detection(self): """Public paths are correctly identified""" from server.api.auth_jwt import _is_public_path assert _is_public_path("/api/auth/login") is True assert _is_public_path("/api/auth/refresh") is True assert _is_public_path("/api/agent/heartbeat") is True assert _is_public_path("/health") is True assert _is_public_path("/ws/alerts") is True assert _is_public_path("/api/settings/bing-wallpapers", "GET") is True def test_protected_path_detection(self): """Protected paths are correctly identified""" from server.api.auth_jwt import _is_public_path assert _is_public_path("/api/servers/") is False assert _is_public_path("/api/settings/") is False assert _is_public_path("/api/sync/files") is False assert _is_public_path("/api/assets/platforms") is False assert _is_public_path("/api/auth/me") is False assert _is_public_path("/api/auth/totp/setup") is False assert _is_public_path("/health/detail") is False assert _is_public_path("/api/settings/bing-wallpapers/sync", "POST") is False assert _is_public_path("/openapi.json") is False class TestAsyncSSHPool: """W7: asyncssh pool tests""" def test_pool_initial_state(self): """Pool starts with zero connections""" from server.infrastructure.ssh.asyncssh_pool import AsyncSSHPool pool = AsyncSSHPool() assert pool.stats == {"total": 0, "active": 0, "idle": 0} def test_pool_config(self): """Pool configuration is reasonable""" from server.infrastructure.ssh.asyncssh_pool import AsyncSSHPool pool = AsyncSSHPool() assert pool.MAX_CONNECTIONS == 100 assert pool.IDLE_TIMEOUT == 300 assert pool.CONNECT_TIMEOUT == 10