Newer
Older
navi-1 / tests / clients / test_terminal_client.py
"""Tests for the Navi Code terminal client."""

from __future__ import annotations

import json
from pathlib import Path

from click.testing import CliRunner

from clients.terminal.cli import main
from clients.terminal.config import Settings
from clients.terminal.render import Renderer
from clients.terminal.state import StateManager


class TestStateManager:
    def test_load_missing_returns_empty(self, tmp_path: Path) -> None:
        mgr = StateManager(tmp_path)
        assert mgr.load() == {}
        assert mgr.get_session_id() is None

    def test_roundtrip_session_id(self, tmp_path: Path) -> None:
        mgr = StateManager(tmp_path)
        mgr.set_session_id("sess-123")
        assert mgr.get_session_id() == "sess-123"
        assert (tmp_path / "state.json").exists()
        data = json.loads((tmp_path / "state.json").read_text())
        assert data == {"session_id": "sess-123"}

    def test_clear_session_id(self, tmp_path: Path) -> None:
        mgr = StateManager(tmp_path)
        mgr.set_session_id("sess-123")
        mgr.clear_session_id()
        assert mgr.get_session_id() is None


class TestRenderer:
    def test_stream_delta_prints_inline(self, capsys) -> None:
        renderer = Renderer()
        renderer.render({"type": "stream_delta", "delta": "hello"})
        captured = capsys.readouterr()
        assert "hello" in captured.out

    def test_error_prints_red(self, capsys) -> None:
        renderer = Renderer()
        renderer.render({"type": "error", "message": "boom"})
        captured = capsys.readouterr()
        assert "boom" in captured.out

    def test_tool_started_shown_when_events_enabled(self, capsys) -> None:
        renderer = Renderer(show_events=True)
        renderer.render({"type": "tool_started", "tool": "terminal", "args": {"cmd": "ls"}})
        captured = capsys.readouterr()
        assert "terminal" in captured.out

    def test_tool_started_hidden_when_events_disabled(self, capsys) -> None:
        renderer = Renderer(show_events=False)
        renderer.render({"type": "tool_started", "tool": "terminal", "args": {"cmd": "ls"}})
        captured = capsys.readouterr()
        assert captured.out == ""


class TestSettings:
    def test_websocket_url_converts_http_to_ws(self) -> None:
        s = Settings(base_url="http://localhost:8000")
        assert s.websocket_url("abc") == "ws://localhost:8000/ws/sessions/abc"

    def test_websocket_url_converts_https_to_wss(self) -> None:
        s = Settings(base_url="https://navi.example.com")
        assert s.websocket_url("abc") == "wss://navi.example.com/ws/sessions/abc"

    def test_websocket_url_uses_explicit_ws_url(self) -> None:
        s = Settings(ws_url="ws://custom:9000")
        assert s.websocket_url("abc") == "ws://custom:9000/ws/sessions/abc"


class TestCliRunner:
    def test_help_shows_usage(self) -> None:
        runner = CliRunner()
        result = runner.invoke(main, ["--help"])
        assert result.exit_code == 0
        assert "Navi Code" in result.output

    def test_version_shows_version(self) -> None:
        runner = CliRunner()
        result = runner.invoke(main, ["--version"])
        assert result.exit_code == 0
        assert "0.1.0" in result.output