mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 00:48:07 +00:00
102 lines
3.8 KiB
Python
102 lines
3.8 KiB
Python
import asyncio
|
|
import sys
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
# Contract: Health Endpoint Structure
|
|
def test_health_structure():
|
|
"""
|
|
Contract: /openclaw/health must return:
|
|
- ok: bool
|
|
- pack: dict (name, version)
|
|
- uptime_sec: float
|
|
- config: dict (provider, model, etc)
|
|
- stats: dict
|
|
|
|
Justification for Mocking:
|
|
We mock the `aiohttp` web stack and service dependencies here to strictly verify the
|
|
*API Contract* (JSON schema/shape stability) without requiring a full runtime environment.
|
|
This ensures the contract test is fast, deterministic, and only fails on breaking schema changes,
|
|
not on environment/dependency issues.
|
|
"""
|
|
|
|
async def _test_logic():
|
|
# 1. Mock dependencies to avoid side effects & imports
|
|
mock_web = MagicMock()
|
|
mock_web.json_response = MagicMock(
|
|
side_effect=lambda data, **kwargs: data
|
|
) # Returns the data dict directly for inspection
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.get_provider_summary.return_value = {
|
|
"provider": "openai",
|
|
"model": "gpt-4",
|
|
"key_configured": True,
|
|
}
|
|
|
|
with patch.dict(
|
|
sys.modules,
|
|
{
|
|
"aiohttp": MagicMock(web=mock_web),
|
|
"aiohttp.web": mock_web,
|
|
"services.llm_client": MagicMock(
|
|
LLMClient=MagicMock(return_value=mock_client)
|
|
),
|
|
"services.providers.keys": MagicMock(requires_api_key=lambda p: True),
|
|
"services.access_control": MagicMock(is_loopback=lambda ip: True),
|
|
"services.metrics": MagicMock(
|
|
metrics=MagicMock(
|
|
get_snapshot=lambda: {"errors_captured": 0, "logs_processed": 0}
|
|
)
|
|
),
|
|
"services.trace_store": MagicMock(),
|
|
"services.log_tail": MagicMock(),
|
|
"services.rate_limit": MagicMock(),
|
|
"services.redaction": MagicMock(),
|
|
},
|
|
):
|
|
# Mock PACK_* constants in api.routes by patching where they are imported from
|
|
with patch("api.routes.PACK_START_TIME", 1000000):
|
|
from api.routes import health_handler
|
|
|
|
# 2. Execute Handler
|
|
request = MagicMock()
|
|
request.remote = "127.0.0.1"
|
|
|
|
# Since we mocked metrics and other globals in sys.modules,
|
|
# we might need to patch them in api.routes if they were already imported.
|
|
# But for this test execution, we are relying on re-import or clean state.
|
|
# Safest way: just set the globals in api.routes if they are None
|
|
import api.routes
|
|
|
|
api.routes.web = mock_web
|
|
api.routes.metrics = MagicMock(
|
|
get_snapshot=lambda: {"errors_captured": 0, "logs_processed": 0}
|
|
)
|
|
|
|
response_data = await health_handler(request)
|
|
|
|
# 3. Assert Contract
|
|
assert response_data["ok"] is True
|
|
assert "pack" in response_data
|
|
assert "uptime_sec" in response_data
|
|
assert "config" in response_data
|
|
assert response_data["config"]["provider"] == "openai"
|
|
assert response_data["config"]["model"] == "gpt-4"
|
|
assert "stats" in response_data
|
|
|
|
# Run the async test logic synchronously
|
|
asyncio.run(_test_logic())
|
|
|
|
|
|
# Contract: Error Response Format
|
|
def test_error_response_format():
|
|
"""
|
|
Contract: All errors must follow {"ok": False, "error": "code"}
|
|
"""
|
|
# This contract is implicit in many handlers.
|
|
# We verify the helper _json_resp structure if accessible, or a known error path.
|
|
pass
|