feat: OpenClaw WebSocket integration with workspace file preview
- Migrate OpenClaw from HTTP (port 8004) to WebSocket (port 18789) - Add workspace file list and content preview handlers - Add OpenClawStatus component with agent/skills view - Add OpenClawView panel in trader interface - Add Zustand store for OpenClaw state management - Fix gateway logging noise (yfinance, websockets) - Fix RunWorkspaceManager.get_agent_asset_dir attribute error - Handle missing workspace files gracefully in preview Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
110
backend/tests/test_openclaw_service_app.py
Normal file
110
backend/tests/test_openclaw_service_app.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# -*- 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 list_cron_jobs(self):
|
||||
return {"jobs": [{"id": "job-1", "name": "Daily sync"}]}
|
||||
|
||||
def list_approvals(self):
|
||||
return {"approvals": [{"id": "ap-1", "status": "pending"}]}
|
||||
|
||||
|
||||
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()["runtimeVersion"] == "2026.3.24"
|
||||
assert sessions.status_code == 200
|
||||
assert len(sessions.json()["sessions"]) == 2
|
||||
assert session.status_code == 200
|
||||
assert session.json()["session"]["agentId"] == "main"
|
||||
assert history.status_code == 200
|
||||
assert history.json()["limit"] == 5
|
||||
assert cron.status_code == 200
|
||||
assert cron.json()["jobs"][0]["id"] == "job-1"
|
||||
assert approvals.status_code == 200
|
||||
assert approvals.json()["approvals"][0]["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
|
||||
Reference in New Issue
Block a user