"""Unit tests for NaviWebSocketClient.send message framing.
``send`` accepts either a plain string (wrapped as a ``message``) or a dict
(sent as-is, with ``cwd`` defaulted) — the latter carries typed control
messages such as ``{"type": "compact"}``. These tests fake the socket so no
network is needed.
"""
from __future__ import annotations
import asyncio
import json
import pytest
from clients.terminal.ws_client import NaviWebSocketClient
class _FakeWs:
def __init__(self) -> None:
self.sent: list[str] = []
async def send(self, raw: str) -> None:
self.sent.append(raw)
def _client() -> NaviWebSocketClient:
client = NaviWebSocketClient("sess")
client._ws = _FakeWs() # type: ignore[attr-defined]
return client
def _sent_payloads(client: NaviWebSocketClient) -> list[dict]:
return [json.loads(raw) for raw in client._ws.sent] # type: ignore[attr-defined]
def test_send_string_wraps_as_message_with_cwd() -> None:
client = _client()
asyncio.run(client.send("hello"))
[payload] = _sent_payloads(client)
assert payload == {"type": "message", "content": "hello", "cwd": str(client._cwd)}
def test_send_dict_passes_through_with_default_cwd() -> None:
client = _client()
asyncio.run(client.send({"type": "compact"}))
[payload] = _sent_payloads(client)
assert payload["type"] == "compact"
# cwd is defaulted in if absent.
assert payload["cwd"] == str(client._cwd)
def test_send_dict_keeps_existing_cwd() -> None:
client = _client()
asyncio.run(client.send({"type": "compact", "cwd": "/custom"}))
[payload] = _sent_payloads(client)
assert payload == {"type": "compact", "cwd": "/custom"}
def test_send_raises_when_not_connected() -> None:
client = NaviWebSocketClient("sess") # no _ws set
with pytest.raises(RuntimeError, match="not connected"):
asyncio.run(client.send({"type": "compact"}))