2026-04-16 12:58:05 -03:00
|
|
|
//! Focused clipboard-read coverage for the client keyboard helper surface.
|
|
|
|
|
//!
|
|
|
|
|
//! Scope: isolate clipboard command and fallback reader behavior so the
|
|
|
|
|
//! keyboard extra contract stays below the hygiene size cap.
|
|
|
|
|
//! Targets: `client/src/input/keyboard.rs`.
|
|
|
|
|
//! Why: clipboard sourcing must stay predictable across operator overrides,
|
|
|
|
|
//! fallback tools, and coverage-mode shells.
|
|
|
|
|
|
|
|
|
|
mod keymap {
|
|
|
|
|
pub use lesavka_client::input::keymap::*;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(warnings)]
|
|
|
|
|
mod keyboard_clipboard_contract {
|
|
|
|
|
include!(env!("LESAVKA_CLIENT_KEYBOARD_SRC"));
|
|
|
|
|
|
|
|
|
|
use serial_test::serial;
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
use temp_env::with_var;
|
|
|
|
|
use tempfile::tempdir;
|
|
|
|
|
|
|
|
|
|
fn write_executable(dir: &Path, name: &str, body: &str) {
|
|
|
|
|
let path = dir.join(name);
|
|
|
|
|
fs::write(&path, body).expect("write script");
|
|
|
|
|
let mut perms = fs::metadata(&path).expect("metadata").permissions();
|
|
|
|
|
perms.set_mode(0o755);
|
|
|
|
|
fs::set_permissions(path, perms).expect("chmod");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn with_fake_path_command(name: &str, script_body: &str, f: impl FnOnce()) {
|
|
|
|
|
let dir = tempdir().expect("tempdir");
|
|
|
|
|
write_executable(dir.path(), name, script_body);
|
|
|
|
|
let prior = std::env::var("PATH").unwrap_or_default();
|
|
|
|
|
let merged = if prior.is_empty() {
|
|
|
|
|
dir.path().display().to_string()
|
|
|
|
|
} else {
|
|
|
|
|
format!("{}:{prior}", dir.path().display())
|
|
|
|
|
};
|
|
|
|
|
with_var("PATH", Some(merged), f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[serial]
|
|
|
|
|
fn read_clipboard_text_uses_fallback_tool_when_available() {
|
|
|
|
|
let wl_paste = "#!/usr/bin/env sh\nprintf 'fallback-clipboard'\n";
|
|
|
|
|
with_var("LESAVKA_CLIPBOARD_CMD", None::<&str>, || {
|
|
|
|
|
with_fake_path_command("wl-paste", wl_paste, || {
|
|
|
|
|
let text = read_clipboard_text().expect("fallback clipboard text");
|
|
|
|
|
assert_eq!(text, "fallback-clipboard");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[serial]
|
|
|
|
|
fn read_clipboard_text_returns_none_when_command_is_empty_and_fallback_fails() {
|
|
|
|
|
let empty_path = tempdir().expect("tempdir");
|
|
|
|
|
temp_env::with_vars(
|
|
|
|
|
[
|
|
|
|
|
("LESAVKA_CLIPBOARD_CMD", Some("printf ''")),
|
|
|
|
|
("PATH", empty_path.path().to_str()),
|
|
|
|
|
],
|
|
|
|
|
|| {
|
|
|
|
|
with_fake_path_command("wl-paste", "#!/usr/bin/env sh\nexit 1\n", || {
|
|
|
|
|
assert!(read_clipboard_text().is_none());
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
#[cfg(coverage)]
|
|
|
|
|
#[serial]
|
|
|
|
|
fn read_clipboard_text_prefers_nonempty_command_output_in_coverage() {
|
|
|
|
|
with_var(
|
|
|
|
|
"LESAVKA_CLIPBOARD_CMD",
|
|
|
|
|
Some("printf 'coverage-clipboard'"),
|
|
|
|
|
|| {
|
|
|
|
|
let text = read_clipboard_text().expect("coverage clipboard text");
|
|
|
|
|
assert_eq!(text, "coverage-clipboard");
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-23 03:49:49 -03:00
|
|
|
#[test]
|
|
|
|
|
#[cfg(coverage)]
|
|
|
|
|
#[serial]
|
|
|
|
|
fn read_clipboard_text_ignores_failed_command_even_with_stdout() {
|
|
|
|
|
let dir = tempdir().expect("tempdir");
|
|
|
|
|
write_executable(
|
|
|
|
|
dir.path(),
|
|
|
|
|
"sh",
|
|
|
|
|
"#!/bin/sh\nprintf 'stale-clipboard'\nexit 1\n",
|
|
|
|
|
);
|
|
|
|
|
temp_env::with_vars(
|
|
|
|
|
[
|
|
|
|
|
("LESAVKA_CLIPBOARD_CMD", Some("ignored")),
|
|
|
|
|
("PATH", dir.path().to_str()),
|
|
|
|
|
],
|
|
|
|
|
|| {
|
|
|
|
|
assert!(read_clipboard_text().is_none());
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 12:58:05 -03:00
|
|
|
#[test]
|
|
|
|
|
#[cfg(coverage)]
|
|
|
|
|
#[serial]
|
|
|
|
|
fn read_clipboard_text_tolerates_missing_shell_in_coverage() {
|
|
|
|
|
let dir = tempdir().expect("tempdir");
|
|
|
|
|
with_var(
|
|
|
|
|
"LESAVKA_CLIPBOARD_CMD",
|
|
|
|
|
Some("printf 'coverage-clipboard'"),
|
|
|
|
|
|| {
|
|
|
|
|
with_var(
|
|
|
|
|
"PATH",
|
|
|
|
|
Some(dir.path().to_string_lossy().to_string()),
|
|
|
|
|
|| {
|
|
|
|
|
assert!(read_clipboard_text().is_none());
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|