"""Capability probe against a real, complex third-party TUI: the `grok` CLI. Everything here is strictly read-only from grok's point of view: we only ever send Down/Up (menu highlight movement) and never press Enter on its prompt, so no prompt is ever submitted to a model and no tool/agent action can run. Skipped entirely when `grok` isn't installed, since it's a local dev tool, not a project dependency. """ from __future__ import annotations import shutil import time import uuid from pathlib import Path import pytest from PIL import Image from tmux_shot import TmuxApp, frames_to_gif pytestmark = pytest.mark.skipif(shutil.which("grok") is None, reason="grok CLI not installed on this machine") def test_grok_doctor_screen_renders_correctly(out_dir: Path) -> None: session = f"tmux_shot_grok_doctor_{uuid.uuid4().hex[:8]}" app = TmuxApp(session, command="grok doctor", width=100, height=35) try: text = app.wait_for("issue", timeout=15) assert "Checks not completed" in text path = app.screenshot(out_dir / "doctor.png") img = Image.open(path) assert img.width == 100 * round(img.width / 100) # sane multiple-of-cols size assert img.height > 0 finally: try: app.kill() except Exception: pass def test_grok_welcome_screen_and_menu_navigation_produce_a_movie(out_dir: Path, tmp_path: Path) -> None: scratch_cwd = tmp_path / "grok_scratch" scratch_cwd.mkdir() session = f"tmux_shot_grok_welcome_{uuid.uuid4().hex[:8]}" app = TmuxApp(session, command=f"grok --cwd {scratch_cwd}", width=100, height=35) frames: list[str] = [] try: app.wait_for("Grok Build", timeout=15) time.sleep(0.3) # let the box-drawing/logo finish painting after the text appears frames.append(app.screenshot(out_dir / "01_welcome.png")) # Move the menu highlight down twice, screenshotting between moves. Arrow # keys only -- never Enter, so nothing gets submitted to grok's model. for i, _ in enumerate(range(2), start=2): app.send_keys("Down", enter=False) time.sleep(0.3) frames.append(app.screenshot(out_dir / f"{i:02d}_menu.png")) assert len(frames) == 3 for f in frames: assert Path(f).stat().st_size > 0 movie_path = frames_to_gif(frames, out_dir / "grok_welcome.gif", duration_ms=700) with Image.open(movie_path) as gif: assert gif.is_animated assert gif.n_frames == 3 finally: try: app.kill() except Exception: pass