test: check what a real terminal renders for multi, zellij, and the TUI

tests/16-render.sh runs tmux, zellij, and the TUI in xterm on Xvfb,
takes screenshots, and reads them back with tesseract: remote prompts
in all panes, borders and titles with the hosts, [SYNC] appearing and
disappearing, panes side by side, broadcast output in every pane and
input in one pane only without it, windows split by panes_per_window,
the status bar, and TUI marks. Screenshots stay in testenv/.artifacts.

OCR reads three preprocessing variants (plain, stretched for dim gray,
brightest channel for colored text) and normalizes characters that
DejaVu Sans Mono makes ambiguous (1/l, C/().

The screenshots showed tmux cutting the session name in the status bar
to "[netssh-pv"; netssh multi now widens status-left-length for its
own session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sebastian UnterschützandClaude Opus 5.5 committed 2026-11-14 13:14:34 +01:00
1 parent a31aab4110
commit 699b9469b6
12 files changed
+194 -5

No files matched your search

+23 -1
View File
@@ -57,6 +57,7 @@ public 10.231.0.0/24 + fd00:30::/64 mgmt 10.231.1.0/24 prod 10.231.2
| `tests/NN-*.sh` | Test files; each runs in a fresh `HOME`. |
| `tests/drive.py` | Drives `netssh configure` in huh's accessible mode. |
| `.keys/`, `.state/` | Generated test key and seed output (git-ignored). |
| `.artifacts/` | Screenshots from `tests/16-render.sh` (git-ignored). |
## Writing tests
@@ -82,9 +83,30 @@ reads the screen with `tmux capture-pane`. The multi test (`15-multi.sh`)
opens panes in real tmux and zellij sessions and checks that broadcast typing
reaches every node.
## What a user sees: `16-render.sh`
The render test runs tmux, zellij, and the TUI in a real terminal emulator —
xterm on a virtual X server (Xvfb) — takes screenshots, and reads them back
with OCR (tesseract). It checks what is actually drawn: remote prompts in all
panes, borders and titles with the host names, `[SYNC]` appearing and
disappearing, panes side by side, broadcast output in every pane, input in one
pane only without broadcast, the status bar, and the TUI marks.
```sh
testenv/test.sh render # then look at the screenshots:
ls testenv/.artifacts/ # tmux-1.png, zellij-2.png, tui-3.png, …
```
Helpers in `lib.sh`: `start_screen`/`stop_screen`, `term CMD…` (full-screen
xterm), `shot NAME`, `screen_shows NAME TEXT…`, `screen_count NAME TEXT`.
OCR reads each screenshot in three preprocessing variants (plain, stretched for
dim gray, brightest channel for colored text) and normalizes characters it
confuses in DejaVu Sans Mono (`1`/`l`, `C`/`(`), so checks stay robust without
becoming vague.
## Not covered
- The installer (`install.sh`) downloads release assets from Gitea; it is tested by the Go tests with local fixtures.
- macOS paths and behaviour.
- `netssh uninstall` runs only with `--dry-run`, so the client keeps its binary.
- tmux and zellij run headless inside the client; the checks read their state (`tmux list-panes`, `zellij action dump-layout`) and screen contents, not what a real terminal would render.
- Rendering is checked in xterm with DejaVu Sans Mono. Other terminals and fonts may differ, e.g. zellij's Powerline arrows need a Nerd Font.