"""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"