"""Smoke tests for the Navi Code TUI."""
from __future__ import annotations
from pathlib import Path
import pytest
from clients.terminal.tui.tui_app import NaviCodeTui
@pytest.fixture(autouse=True)
def tmp_state_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
"""Override the state dir so tests never touch ~/.navi_code."""
from clients.terminal import config
original = config.settings.state_dir
config.settings.state_dir = tmp_path
import clients.terminal.tui.settings as settings_module
settings_module._tui_settings = None
yield tmp_path
config.settings.state_dir = original
settings_module._tui_settings = None
@pytest.mark.anyio
async def test_tui_mounts_widgets() -> None:
"""The TUI app mounts chat, status, and input widgets."""
async with NaviCodeTui(new_session=True).run_test() as pilot:
await pilot.pause()
assert pilot.app.query_one("ChatPanel") is not None
assert pilot.app.query_one("StatusPanel") is not None
assert pilot.app.query_one("InputBox") is not None
@pytest.mark.anyio
async def test_user_message_appears_in_chat() -> None:
"""Typing a message and submitting adds it to the chat panel."""
async with NaviCodeTui(new_session=True).run_test() as pilot:
await pilot.pause()
input_box = pilot.app.query_one("InputBox")
input_box._input.value = "hello"
await pilot.press("enter")
await pilot.pause()
chat = pilot.app.query_one("ChatPanel")
assert any(item.kind == "user_message" and item.content == "hello" for item in chat._model.items)
@pytest.mark.anyio
async def test_ws_event_renders_in_chat() -> None:
"""A synthetic WebSocket stream_delta is added to the assistant response."""
async with NaviCodeTui(new_session=True).run_test() as pilot:
await pilot.pause()
chat = pilot.app.query_one("ChatPanel")
chat.handle_ws_event({"type": "stream_start"})
chat.handle_ws_event({"type": "stream_delta", "delta": "hi"})
await pilot.pause()
assert chat._model._current_assistant is not None
assert chat._model._current_assistant.content == "hi"
@pytest.mark.anyio
async def test_unknown_slash_command_shows_error() -> None:
"""Unknown slash command produces an error item in chat."""
async with NaviCodeTui(new_session=True).run_test() as pilot:
await pilot.pause()
input_box = pilot.app.query_one("InputBox")
input_box._input.value = "/notacommand"
await pilot.press("enter")
await pilot.pause()
chat = pilot.app.query_one("ChatPanel")
assert any(item.kind == "error" for item in chat._model.items)
@pytest.mark.anyio
async def test_status_panel_shows_backend_and_theme() -> None:
"""Status panel displays backend URL and current theme."""
async with NaviCodeTui(new_session=True).run_test() as pilot:
await pilot.pause()
status = pilot.app.query_one("StatusPanel")
backend_text = str(status._backend.render())
theme_text = str(status._theme.render())
assert "Backend:" in backend_text
assert "Theme: gnexus-dark" in theme_text