- Delete backend/cli.py and all CLI-specific tests (test_cli.py, test_openclaw_cli_service.py, test_skills_cli.py) - Remove evotraders console script from pyproject.toml - Update README/CLAUDE.md to reference python backend/main.py instead of CLI - Add pytest-asyncio to dev dependencies - Enhance EvoAgent with reload_runtime_assets and backward-compat attrs - Align tests with updated API semantics and gateway process models Constraint: CLI is deprecated in favor of split-service runtime model Confidence: high Scope-risk: moderate
149 lines
5.2 KiB
Python
149 lines
5.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Tests for the extracted OpenClaw service app surface."""
|
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
from backend.apps.openclaw_service import create_app
|
|
from backend.api import openclaw as openclaw_module
|
|
|
|
|
|
class _FakeOpenClawCliService:
|
|
def health(self):
|
|
return {
|
|
"status": "healthy",
|
|
"service": "openclaw-service",
|
|
"base_command": ["openclaw"],
|
|
"cwd": "/tmp/openclaw",
|
|
"binary_resolved": True,
|
|
"reference_entry_available": True,
|
|
"timeout_seconds": 15.0,
|
|
}
|
|
|
|
def status(self):
|
|
return {"runtimeVersion": "2026.3.24"}
|
|
|
|
def list_sessions(self):
|
|
return {
|
|
"sessions": [
|
|
{"key": "main/session-1", "agentId": "main"},
|
|
{"key": "analyst/session-2", "agentId": "analyst"},
|
|
]
|
|
}
|
|
|
|
def get_session(self, session_key: str):
|
|
for session in self.list_sessions()["sessions"]:
|
|
if session["key"] == session_key:
|
|
return session
|
|
raise KeyError(session_key)
|
|
|
|
def get_session_history(self, session_key: str, *, limit: int = 20):
|
|
return {
|
|
"sessionKey": session_key,
|
|
"limit": limit,
|
|
"items": [{"role": "assistant", "text": "hello"}],
|
|
}
|
|
|
|
def status_model(self):
|
|
from shared.models.openclaw import OpenClawStatus
|
|
return OpenClawStatus(runtimeVersion="2026.3.24")
|
|
|
|
def get_session_model(self, session_key: str):
|
|
from shared.models.openclaw import SessionEntry
|
|
for session in self.list_sessions()["sessions"]:
|
|
if session["key"] == session_key:
|
|
return SessionEntry.model_validate(session, strict=False)
|
|
raise KeyError(session_key)
|
|
|
|
def list_sessions_model(self):
|
|
from shared.models.openclaw import SessionsList, SessionEntry
|
|
sessions = [
|
|
SessionEntry.model_validate(s, strict=False)
|
|
for s in self.list_sessions()["sessions"]
|
|
]
|
|
return SessionsList(sessions=sessions)
|
|
|
|
def get_session_history_model(self, session_key: str, *, limit: int = 20):
|
|
from shared.models.openclaw import SessionHistory
|
|
raw = self.get_session_history(session_key, limit=limit)
|
|
return SessionHistory(
|
|
sessionKey=raw["sessionKey"],
|
|
session_id=None,
|
|
events=raw["items"],
|
|
history=raw["items"],
|
|
raw_text=None,
|
|
)
|
|
|
|
def list_cron_jobs(self):
|
|
return {"jobs": [{"id": "job-1", "name": "Daily sync"}]}
|
|
|
|
def list_cron_jobs_model(self):
|
|
from shared.models.openclaw import CronList
|
|
return CronList.from_raw(self.list_cron_jobs())
|
|
|
|
def list_approvals(self):
|
|
return {"approvals": [{"approvalId": "ap-1", "toolName": "test_tool", "status": "pending"}]}
|
|
|
|
def list_approvals_model(self):
|
|
from shared.models.openclaw import ApprovalsList
|
|
return ApprovalsList.from_raw(self.list_approvals())
|
|
|
|
|
|
def test_openclaw_service_routes_are_exposed():
|
|
app = create_app()
|
|
paths = {route.path for route in app.routes}
|
|
|
|
assert "/health" in paths
|
|
assert "/api/status" in paths
|
|
assert "/api/openclaw/status" in paths
|
|
assert "/api/openclaw/sessions" in paths
|
|
assert "/api/openclaw/sessions/{session_key:path}" in paths
|
|
assert "/api/openclaw/sessions/{session_key:path}/history" in paths
|
|
assert "/api/openclaw/cron" in paths
|
|
assert "/api/openclaw/approvals" in paths
|
|
|
|
|
|
def test_openclaw_service_read_routes():
|
|
app = create_app()
|
|
app.dependency_overrides[openclaw_module.get_openclaw_cli_service] = (
|
|
lambda: _FakeOpenClawCliService()
|
|
)
|
|
|
|
with TestClient(app) as client:
|
|
health = client.get("/health")
|
|
status = client.get("/api/status")
|
|
openclaw_status = client.get("/api/openclaw/status")
|
|
sessions = client.get("/api/openclaw/sessions")
|
|
session = client.get("/api/openclaw/sessions/main/session-1")
|
|
history = client.get("/api/openclaw/sessions/main/session-1/history", params={"limit": 5})
|
|
cron = client.get("/api/openclaw/cron")
|
|
approvals = client.get("/api/openclaw/approvals")
|
|
|
|
assert health.status_code == 200
|
|
assert health.json()["service"] == "openclaw-service"
|
|
assert status.status_code == 200
|
|
assert status.json()["status"] == "operational"
|
|
assert openclaw_status.status_code == 200
|
|
assert openclaw_status.json()["runtime_version"] == "2026.3.24"
|
|
assert sessions.status_code == 200
|
|
assert len(sessions.json()["sessions"]) == 2
|
|
assert session.status_code == 200
|
|
assert session.json()["session"]["agent_id"] == "main"
|
|
assert history.status_code == 200
|
|
assert len(history.json()["events"]) == 1
|
|
assert cron.status_code == 200
|
|
assert cron.json()["jobs"][0]["id"] == "job-1"
|
|
assert approvals.status_code == 200
|
|
assert approvals.json()["approvals"][0]["approval_id"] == "ap-1"
|
|
|
|
|
|
def test_openclaw_service_session_404():
|
|
app = create_app()
|
|
app.dependency_overrides[openclaw_module.get_openclaw_cli_service] = (
|
|
lambda: _FakeOpenClawCliService()
|
|
)
|
|
|
|
with TestClient(app) as client:
|
|
response = client.get("/api/openclaw/sessions/missing")
|
|
|
|
assert response.status_code == 404
|