74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
"""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
|