Newer
Older
navi-1 / tests / clients / test_render_plain.py
"""Reading-mode (borderless) rendering: registry.render_plain drops Panel chrome.

Every Panel-based renderer must unwrap to a borderless body so a raw terminal
Shift+drag + Ctrl+Shift+C copies clean text (no ``│``/``╭``) in terminals
without OSC 52 support (e.g. GNOME Console).
"""

from __future__ import annotations

import pytest
from rich.panel import Panel
from rich.padding import Padding

from clients.terminal.tui.renderers import default_registry
from clients.terminal.tui.themes import set_active_theme

set_active_theme("gnexus-dark")


def _is_bordered(renderable) -> bool:
    """True if the renderable (or a Padding-wrapped Panel) still carries a border."""
    if isinstance(renderable, Panel):
        return True
    if isinstance(renderable, Padding) and isinstance(renderable.renderable, Panel):
        return True
    return False


@pytest.mark.parametrize(
    "msg",
    [
        {"type": "user_message", "content": "hi"},
        {"type": "assistant_message", "content": "## H\n\n```py\nx=1\n```"},
        {"type": "thinking_block", "content": "reasoning"},
        {"type": "tool_started", "tool": "foo", "args": {"a": 1}},
        {"type": "tool_call", "tool": "foo", "result": "bar", "success": True},
        {"type": "tool_started", "tool": "filesystem", "args": {"action": "read", "path": "x.py"}},
        {"type": "tool_call", "tool": "filesystem", "result": "ok", "success": True, "args": {"action": "read"}},
        {"type": "tool_started", "tool": "spawn_agent", "args": {"task": "do thing"}},
        {"type": "tool_call", "tool": "spawn_agent", "result": "done", "success": True},
        {"type": "tool_started", "tool": "todo", "args": {}},
        {"type": "tool_call", "tool": "todo", "result": "plan set", "success": True},
        {"type": "error", "message": "boom"},
        {"type": "planning_status", "label": "Analysis"},
        {"type": "plan_ready", "plan": "## Plan\nstep 1"},
        {"type": "turn_meta", "elapsed_seconds": 3},
        {"type": "context_summary", "content": "summarized"},
        {"type": "recall_update", "status": "fired"},
        {"type": "diff", "content": "--- a\n+++ b\n@@\n-x\n+y\n", "path": "f"},
        {"type": "plain", "content": "raw"},
    ],
)
def test_render_plain_has_no_panel_border(msg) -> None:
    reg = default_registry()
    r = reg.render_plain(msg)
    assert not _is_bordered(r), f"render_plain for {msg['type']} still bordered: {r!r}"


def test_render_plain_user_text_is_verbatim() -> None:
    reg = default_registry()
    from rich.text import Text

    r = reg.render_plain({"type": "user_message", "content": "Hello world"})
    assert isinstance(r, Text)
    assert r.plain == "Hello world"