mirror of
https://github.com/lotabout/skim.git
synced 2026-09-10 07:16:23 -04:00
2 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d7b799b9e6
|
fix: make min-height work again (#1168)
* fix: make min-height work again * fix: revert to String and add integration tests * chore: misc warnings * fix: windows tests * fix: ci public api fails because of incompatible deps version between HEAD and release |
||
|
|
88ce5b97ac
|
test: replace tmux e2e harness with cross-platform Zellij harness (#1139)
* test: replace tmux e2e harness with cross-platform Zellij harness Rewrite the end-to-end test harness to drive `sk` through Zellij instead of tmux, keeping the same capabilities and public surface (ZellijController, Keys, wait, sk, the sk_test! DSL and the line!/keys!/out! helpers) so the existing tests port over with only import/type renames. Zellij has no detached-server model like tmux, so the harness spawns a Zellij client attached to an in-process pseudo-terminal via portable-pty (openpty on Unix, ConPTY on Windows). Because Zellij 0.44+ and portable-pty are both cross-platform, the harness — and the tests that only rely on it — are now available on Windows too: the interactive tests (formerly unix.rs) are un-gated. execute.rs, popup.rs and listen.rs stay unix-only for reasons unrelated to the multiplexer (PermissionsExt, a mock sh/tmux binary, unix sockets). Key harness details: - Session per test via `zellij attach --create` on a fixed 80x24 PTY. - Keys injected as raw terminal bytes with `zellij action write`; screen read back with `zellij action dump-screen [--ansi]`, reversed to match the old bottom-anchored indexing. - A generated config disables startup tips, pane frames, mouse mode and — the crucial bit — the kitty keyboard protocol, so injected legacy escape sequences (arrows, etc.) reach sk. - All zellij CLI calls are run under a timeout and wait() has a wall-clock budget, so a wedged server surfaces as a fast retryable error instead of hanging a test. popup.rs unsets $ZELLIJ and sets $TMUX so skim selects its tmux popup backend (the mock) rather than the zellij one while running inside a Zellij pane. Because each test spins up a full Zellij session, the e2e binaries are put in a serialized nextest test-group; CI installs Zellij (all three OSes) in place of tmux, and the obsolete tmux setup-scripts are removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * ci: fix rustfmt and stop Windows from cancelling the other nextest legs - Run `cargo +nightly fmt` on the new Zellij harness (rustfmt CI was red). - Set `fail-fast: false` on the nextest matrix so a failing OS leg no longer cancels the others, giving a clear pass/fail signal per platform. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * ci: install zellij via winget on Windows taiki-e/install-action has no prebuilt Zellij binary for Windows and falls back to `cargo install zellij`, which fails building openssl-sys from source on the runner. Install via winget on Windows instead (taiki-e still handles Linux/macOS), and expose winget's shim dir on PATH for the test step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test/ci: address review feedback on the Zellij harness - Pin the Windows winget Zellij install to 0.44.3 to match the Linux/macOS runners (reproducible CI). - Drop the unused `&locale` YAML anchor (actionlint flagged it). - `wait` now surfaces the last predicate error on timeout instead of a generic one, so a persistent failure keeps its diagnostic cause. - `output_with_timeout` tears down the child and reader threads on a `try_wait` error instead of leaking them. - Add rustdoc to the public harness surface (`sk`, `wait`, `Keys`, `ZellijController` and its methods). Deliberately not changed: a non-zero `zellij` exit is still not treated as an error (some `zellij action` calls exit non-zero in transient states — e.g. inline `sk` viewport teardown — while returning usable output; propagating it broke `inline_clear_on_exit`), and `to_lines` keeps trimming to preserve the tmux-parity bottom-anchored indexing the ported tests rely on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * ci: put the real zellij.exe dir on PATH for the Windows test step The winget install succeeds, but its Links shim wasn't reliably visible to the `cargo nextest` step's processes, so `which("zellij")` failed and every interactive test panicked at setup. Locate the installed zellij.exe under the WinGet Packages dir and add its directory to GITHUB_PATH instead, failing the step loudly if it isn't found. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * ci: reload PATH from registry after the MSI zellij install on Windows The winget Zellij package is an MSI installer that installs to Program Files and updates the machine PATH in the registry, not a portable under WinGet\Packages — so the previous "search Packages" lookup threw. Reload PATH from the machine/user registry values (with a Program Files fallback), then export zellij's directory via GITHUB_PATH for the test step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test/ci: gate interactive e2e tests off Windows Enabling the interactive tests on the Windows runner surfaced a real gap: the PATH/install issues are fixed (winget install works), but under the Windows runner's ConPTY the Zellij session never renders — dump-screen stays empty and wait_ready times out with "pane not rendered yet" for every interactive test. That's a harness-runtime gap on Windows (and sk's escape-code disambiguation on Windows would be a further blocker), so gate interactive.rs `#![cfg(not(windows))]` with a TODO, keeping the harness code cross-platform. Since no Windows test now uses the harness, drop the winget Zellij install from the Windows leg; Linux/macOS still install it via taiki-e. Adjust the docs that claimed the e2e tests run on Windows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): gate Zellij harness tests to Linux only The Zellij-backed e2e harness renders reliably under the Linux CI runner, but on the macOS and Windows runners the pane never comes up under their PTY (`wait_ready` times out with "pane not rendered yet"). Restrict all four e2e test files (interactive, execute, popup, listen) to `#![cfg(target_os = "linux")]`, install Zellij only on the Linux runner, and update the harness/agent/architecture docs to match. The harness code stays cross-platform so macOS/Windows e2e can be re-enabled once their runners render the session. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): make the Zellij harness render on macOS and Windows The Zellij e2e harness previously only came up reliably on the Linux CI runner; on macOS and Windows the pane never rendered and every e2e test timed out with "pane not rendered yet". Root cause (surfaced by capturing the Zellij client's PTY output): Zellij's client/server startup handshake is racy — the client occasionally dies with "Received empty unknown from server" and the session never renders. It's rare on Linux (flaky) but frequent on the cold macOS/Windows runners. Harden the harness so it renders everywhere instead of gating tests to Linux: - Detect a dead session fast (drain thread flags client PTY EOF) and respawn a fresh session, up to SESSION_SPAWN_ATTEMPTS times, instead of waiting out the whole render budget and failing. - Resolve the pane's shell to an absolute `bash` path via `which`; the Zellij server's own environment may not have `bash` on PATH on the macOS/Windows runners, which would leave the pane with no shell to render. - Nudge the client's terminal size until the server gives the pane a non-zero geometry to render into (the initial size can be dropped under ConPTY / a cold runner). - Give the first render its own longer budget and, on timeout, surface a tail of the Zellij client output for diagnosing runners we can't reproduce locally. Un-gate the tests accordingly: interactive.rs (pure harness) now runs on Linux, macOS and Windows; execute.rs/popup.rs/listen.rs go back to #![cfg(unix)] (Linux + macOS) — their Windows-incompatibility is POSIX mock binaries / a unix socket, unrelated to the multiplexer. CI installs Zellij on all three OSes (taiki-e on Linux/macOS, winget on Windows) and the nextest job gets a 45-minute cap so a harness regression fails fast. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): fix macOS session-name rejection via short ZELLIJ_SOCKET_DIR The macOS runner failed every Zellij e2e test at CLI-parse time: error: Invalid value "skim_e2e_..." for '--session <SESSION>': session name must be less than 0 characters This is not the render race the previous commit addressed. Zellij places each session's unix socket at `$ZELLIJ_SOCKET_DIR/<protocol>/<session>`, and a unix socket path is length-capped by the OS (~104 bytes on macOS). Zellij's default base is `$TMPDIR/zellij-<uid>`; on the macOS runners `$TMPDIR` is a long `/var/folders/…` path that leaves ~0 bytes for the session name, so Zellij rejects every name and the client exits before it attaches (zellij-org/zellij#4211). Linux's short `/run`|`/tmp` base never hits this, which is why it only failed on macOS. - Export ZELLIJ_SOCKET_DIR=/tmp/skim-zj (a short base) on every zellij invocation — the attached client, `action`, and `run` — so they share a short socket path well under the cap on Linux and macOS alike. - Shorten session names (`sk_<=10 chars_<6 rand>`): several were derived from long test names (e.g. execute_interactive_child_keeps_receiving_ keys_fullscreen) and exceeded Zellij's ~36-char limit and ate socket budget; the random suffix still keeps them unique. Also fix a stale doc command in AGENTS.md (`cargo nextest --tests` -> `cargo nextest run --tests`), per PR review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): answer the DSR cursor-position probe so Windows renders The Windows nextest leg hung on every interactive.rs e2e test: Error: pane not rendered within 60s. zellij client output tail: \u{1b}[6n The captured client output was a single `ESC[6n` — a Device Status Report requesting the cursor position. Under the Windows ConPTY the Zellij client probes the terminal size by asking for the cursor position and blocks until the terminal replies; on Unix the size comes from the PTY ioctl, so the client never waits (which is why only Windows hung). The harness owns the master PTY — it *is* the terminal — so the drain thread now watches for `ESC[6n` and writes back a Cursor Position Report (`ESC[24;80R`, reporting the 24x80 pane). This unblocks the client so the pane renders. The reply is harmless on Linux/macOS (all 45 e2e tests still pass there), keeping interactive.rs on all three platforms. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): address review nits in the Zellij harness Follow-ups from PR review, none affecting the cross-platform fixes: - zellij_socket_dir() now returns io::Result and propagates a create_dir_all failure through run()/action()/spawn_once() instead of swallowing it, so a socket-dir problem surfaces directly rather than as a confusing downstream Zellij error. - Fix a latent typo in the (currently unused) assert_line!/line! macro: std::io::std::io::Error{,Kind} -> std::io::Error / std::io::ErrorKind, so the macro compiles if a test ever uses it. - tempfile() returns an InvalidData error instead of panicking on a non-UTF-8 temp path. Skipped the reviewer's suggestion to stop trimming captured output: the trim is load-bearing. It drops Zellij's blank padding rows so capture()[0] is the bottom content line that every test indexes against; stripping only CR/LF would reintroduce ~20 empty rows and shift every index. No test exercises intentionally-spaced items, so there is no real defect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): silence unused_assignments warning in wait() `last_err` was initialised to `None` and always overwritten before it could be read, so the initial assignment was dead (unused_assignments warning at the top of every test build). Return the current predicate error directly on timeout instead of stashing it — same behaviour (the most recent error is surfaced), no dead variable, no warning. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): wrap assert_line! timeout error to 120 columns Pure formatting: split the Err/Error::new/format! construction in the (rustfmt-skipped) assert_line! macro body across lines to satisfy the repo's 120-column limit. No behaviour change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): guard against [-0] in the negative-index DSL macro @method_neg_dispatch used `lines.len() >= $idx`, which is always true for $idx == 0, so `@capture[-0]` would index `lines[lines.len()]` and panic. Require `$idx > 0` in both the predicate and diagnostic paths so a `[-0]` index falls through to the graceful "not enough lines" / "<no line>" handling instead. No current test uses negative indices; this only closes the latent edge case. Per PR review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): use forward slashes for Windows paths in the bash command With the DSR fix the Windows pane now renders and runs the command, which surfaced the next issue: the harness drives a `bash` shell but embedded native Windows paths (backslashes) into the command string. bash treats `\` as an escape, so `.\target\release\sk.exe` collapsed to `.targetreleasesk.exe` ("command not found") and the `C:\Users\...` redirect/mv targets would mangle the same way. Convert `\` to `/` for the `sk` binary and the outfile when building the bash command in sk(); bash on Windows accepts `./target/release/sk.exe` and `C:/Users/...`. On Unix the paths have no backslashes so it is a no-op, and the stored outfile the test reads back keeps native separators. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU * test(e2e): reap the Zellij client child in Drop ZellijController::drop killed the client with child.kill() but never waited on it, so on Unix each dropped controller left a zombie until the test binary exited — and many controllers are created per binary. Pair the kill with child.wait() (matching output_with_timeout) so the process is reaped immediately. Per PR review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wTqRsi31RYJXEM3ZZQhQU --------- Co-authored-by: Claude <noreply@anthropic.com> |
Renamed from tests/unix.rs (Browse further)