Files
aicc-py/tests/test_websocket.py
T
Emil Shanaty 1314314567 feat: conformance test runner + protocol fixes
- conformance.py: declarative scenario runner (subset matcher, $kind/$gt/
  $enum/$required assertions, call_id/session_id echo checks), reference
  bridge, CLI entry (python -m aicc.conformance)
- bridge.py: protocol version check before parsing (protocol_mismatch),
  session expiry handling (session_expired), malformed tool_call ->
  invalid_input, emit_event() for async events
- client.py: Self return type
- in_process.py: drain bridge event queue after response (event delivery),
  Self return type
- websocket.py: Self return type, best-effort shutdown
- tests: 14 passing (incl. conformance scenarios, 9/9 core scenarios)
- ruff: all checks pass
2026-08-08 03:27:14 +03:00

31 lines
1.0 KiB
Python

"""End-to-end test over WebSocket: server + client in the same event loop."""
from __future__ import annotations
import pytest
from aicc import AICCClient, Bridge
from aicc.transport import WebSocketClientTransport, WebSocketServer
@pytest.mark.asyncio
async def test_websocket_roundtrip():
bridge = Bridge(name="ws-room")
@bridge.tool(description="Echo a value.")
async def echo(value: str = "") -> dict:
return {"value": value}
async with WebSocketServer(bridge, port=0) as server:
# port=0 -> OS-assigned; read it back from the server object
port = server._server.sockets[0].getsockname()[1] # type: ignore[union-attr]
uri = f"ws://127.0.0.1:{port}"
async with AICCClient(WebSocketClientTransport(uri)) as client:
manifest = await client.handshake()
assert manifest.world.name == "ws-room"
res = await client.call_tool("echo", {"value": "hi"})
assert res.ok
assert res.output == {"value": "hi"}