Newer
Older
navi-1 / tests / clients / test_terminal_renderer.py
"""Tests for the terminal tool-call renderer (action-aware cards)."""

from __future__ import annotations

from rich.console import Console
from rich.text import Text

from clients.terminal.tui.renderers.terminal import TerminalToolResultRenderer
from clients.terminal.tui.themes import get_active_theme, set_active_theme


def _render_text(renderable) -> str:
    console = Console(record=True, width=80, force_terminal=True, color_system=None)
    console.print(renderable)
    return console.export_text()


def _body(panel):
    r = panel.renderable
    if isinstance(r, Text):
        return r
    return r


def _msg(action, **kw):
    msg = {"type": "tool_call", "tool": "terminal", "args": {"action": action}, "success": True}
    msg.update(kw)
    return msg


def test_accepts_only_terminal_tool_call() -> None:
    r = TerminalToolResultRenderer()
    assert r.accepts(_msg("run"))
    assert not r.accepts({"type": "tool_call", "tool": "filesystem", "args": {"action": "read"}})
    assert not r.accepts({"type": "tool_started", "tool": "terminal"})


def test_run_shows_command_and_exit_code() -> None:
    set_active_theme("gnexus-dark")
    theme = get_active_theme()
    panel = TerminalToolResultRenderer().render(
        _msg("run", args={"action": "run", "command": "echo hi"}, result="hi", success=True, metadata={"returncode": 0})
    )
    text = _render_text(panel)
    assert "$ echo hi" in text
    assert "hi" in text
    assert "exit 0" in text
    assert "✓" in str(panel.title)


def test_run_failure_marks_exit_code_red() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg("run", args={"action": "run", "command": "false"}, result="", success=False, metadata={"returncode": 1})
    )
    text = _render_text(panel)
    assert "$ false" in text
    assert "exit 1" in text
    assert "✗" in str(panel.title)


def test_open_shows_name_description_pid() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg(
            "open",
            args={"action": "open", "terminal_name": "dev", "description": "dev server", "background": True},
            result="Terminal 'dev' opened in background. PID: 123.",
            success=True,
            metadata={"name": "dev", "description": "dev server", "pid": 123},
        )
    )
    text = _render_text(panel)
    assert "dev" in text
    assert "dev server" in text
    assert "background" in text
    assert "123" in text


def test_list_renders_output_dim() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg("list", result="Active terminals (1):\n  🟢 dev: server", success=True)
    )
    text = _render_text(panel)
    assert "Active terminals" in text
    assert "dev" in text


def test_status_renders_output() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg("status", result="Terminal: dev\nStatus: busy\nPID: 7", success=True)
    )
    text = _render_text(panel)
    assert "Terminal: dev" in text
    assert "busy" in text


def test_send_input_echo() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg("send_input", result="Sent input to 'dev'.", success=True)
    )
    text = _render_text(panel)
    assert "Sent input" in text


def test_close_message() -> None:
    set_active_theme("gnexus-dark")
    panel = TerminalToolResultRenderer().render(
        _msg("close", result="Terminal 'dev' closed.", success=True)
    )
    text = _render_text(panel)
    assert "closed" in text


def test_run_truncates_long_output() -> None:
    set_active_theme("gnexus-dark")
    big = "\n".join(f"line {i}" for i in range(300))
    panel = TerminalToolResultRenderer().render(
        _msg("run", args={"action": "run", "command": "heavy"}, result=big, success=True, metadata={"returncode": 0})
    )
    text = _render_text(panel)
    assert "lines truncated]" in text
    assert "line 299" in text
    assert "line 0" not in text