use std::collections::HashMap;
use crate::tui::remote_upload::{Channel, Env, choose, guidance, is_remote, multiplexed, scp_hint};
fn env(pairs: &[(&str, &str)]) -> Env {
Env {
vars: pairs
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect::<HashMap<_, _>>(),
has_kitten: false,
has_rz: false,
}
}
const SSH: (&str, &str) = ("SSH_CONNECTION", "192.168.1.42 51234 10.0.0.7 22");
#[test]
fn test_remote_is_detected_from_any_of_the_ssh_markers() {
assert!(is_remote(&env(&[SSH])));
assert!(is_remote(&env(&[("SSH_TTY", "/dev/pts/0")])));
assert!(is_remote(&env(&[("SSH_CLIENT", "192.168.1.42 51234 22")])));
assert!(!is_remote(&env(&[("TERM", "xterm-256color")])));
assert!(!is_remote(&env(&[("SSH_CONNECTION", "")])));
}
#[test]
fn test_kitty_wins_when_both_ends_can_do_it() {
let mut e = env(&[SSH, ("TERM", "xterm-kitty")]);
e.has_kitten = true;
assert_eq!(choose(&e), Channel::Kitty);
let e = env(&[SSH, ("TERM", "xterm-kitty")]);
assert_eq!(choose(&e), Channel::ScpHint);
}
#[test]
fn test_zmodem_for_terminals_that_answer_it() {
for term in ["iTerm.app", "WezTerm", "tabby"] {
let mut e = env(&[SSH, ("TERM_PROGRAM", term)]);
e.has_rz = true;
assert_eq!(choose(&e), Channel::Zmodem, "{term} should use zmodem");
}
let mut e = env(&[SSH, ("TERM_PROGRAM", "Apple_Terminal")]);
e.has_rz = true;
assert_eq!(choose(&e), Channel::ScpHint);
}
#[test]
fn test_a_multiplexer_forces_the_hint_tier() {
let mut e = env(&[
SSH,
("TERM", "xterm-kitty"),
("TMUX", "/tmp/tmux-0/default"),
]);
e.has_kitten = true;
assert_eq!(choose(&e), Channel::ScpHint);
let mut e = env(&[SSH, ("TERM_PROGRAM", "iTerm.app"), ("STY", "1234.pts-0")]);
e.has_rz = true;
assert_eq!(choose(&e), Channel::ScpHint);
assert!(multiplexed(&env(&[("TMUX", "x")])));
assert!(!multiplexed(&env(&[SSH])));
}
#[test]
fn test_the_scp_hint_pushes_to_here_rather_than_pulling_from_the_client() {
let e = env(&[SSH, ("USER", "root")]);
let hint = scp_hint(
&e,
"/Users/me/Screenshot 2026-09-01 at 18.18.16.png",
"/root/att",
);
assert!(
hint.starts_with("scp '/Users/me/Screenshot"),
"the client's file is the SOURCE: {hint}"
);
assert!(
hint.ends_with("root@10.0.0.7:/root/att/"),
"#1289: destination is THIS host as the client addressed it: {hint}"
);
assert!(
!hint.contains("192.168.1.42"),
"the client address must not appear at all: {hint}"
);
}
#[test]
fn test_the_hint_falls_back_when_ssh_connection_is_absent() {
let hint = scp_hint(&env(&[("SSH_TTY", "/dev/pts/0")]), "/a.png", "/dest");
assert!(hint.contains("<this-host>"), "{hint}");
assert!(hint.contains("<you>"), "{hint}");
}
#[test]
fn test_a_quote_in_the_path_cannot_break_out_of_the_hint() {
let e = env(&[SSH]);
let hint = scp_hint(&e, "/tmp/it's here.png", "/dest");
assert!(
hint.contains(r"'/tmp/it'\''s here.png'"),
"embedded quote must be escaped: {hint}"
);
}
#[test]
fn test_scp_is_always_the_command_given() {
let mut kitty = env(&[SSH, ("TERM", "xterm-kitty")]);
kitty.has_kitten = true;
let g = guidance(&kitty, "/Users/me/a b.png", "/root/att");
assert!(g.contains("scp"), "{g}");
assert!(
g.contains("'/Users/me/a b.png'"),
"spaces must survive: {g}"
);
assert!(
g.contains("kitten"),
"the better tier is still surfaced: {g}"
);
let mut iterm = env(&[SSH, ("TERM_PROGRAM", "iTerm.app")]);
iterm.has_rz = true;
let g = guidance(&iterm, "/Users/me/a.png", "/root/att");
assert!(g.contains("scp"), "{g}");
assert!(g.contains("rz"), "{g}");
let g = guidance(&env(&[SSH]), "/Users/me/a.png", "/root/att");
assert!(g.contains("scp"), "{g}");
}
#[test]
fn test_no_unverified_command_line_is_presented_as_runnable() {
let mut kitty = env(&[SSH, ("TERM", "xterm-kitty")]);
kitty.has_kitten = true;
let g = guidance(&kitty, "/Users/me/a.png", "/root/att");
assert!(
g.contains("--help"),
"point at the terminal's own docs rather than asserting flags: {g}"
);
}
#[test]
fn test_a_local_session_is_told_the_path_is_simply_wrong() {
let g = guidance(&env(&[("TERM", "xterm-256color")]), "/nope/a.png", "/dest");
assert!(g.contains("does not exist here"), "{g}");
assert!(
!g.contains("scp"),
"no transfer advice when not remote: {g}"
);
}
#[test]
fn test_the_multiplexer_case_explains_itself() {
let g = guidance(&env(&[SSH, ("TMUX", "x")]), "/Users/me/a.png", "/dest");
assert!(g.contains("scp"), "{g}");
assert!(
g.contains("tmux/screen"),
"the user should learn WHY the better tier is unavailable: {g}"
);
}
#[test]
fn test_guidance_names_the_drop_tunnel_for_ssh_sessions_only() {
let e = env(&[
("SSH_CONNECTION", "10.0.0.2 51234 10.0.0.1 22"),
("USER", "root"),
]);
let g = guidance(&e, "/Users/me/a.png", "/root/.opencrabs/tmp");
assert!(g.contains("opencrabs drop-agent"), "{g}");
assert!(
g.contains("ssh -R 127.0.0.1:8765:localhost:8765 root@10.0.0.1"),
"the forward must be addressed to this host as the client reached it: {g}"
);
let local = guidance(&env(&[("TERM", "xterm")]), "/nope/a.png", "/dest");
assert!(
!local.contains("drop-agent"),
"a missing local file is not a remote-copy problem: {local}"
);
}