use super::*;
#[test]
fn target_renders_session_and_bare_pane() {
assert_eq!(TmuxTarget::session("s").as_target(), "=s:");
assert_eq!(TmuxTarget::pane("s", "%2").as_target(), "%2");
assert_eq!(TmuxTarget::pane("s", "1.0").as_target(), "=s:1.0");
}
#[test]
fn exact_session_target_prefixes_equals() {
assert_eq!(exact_session_target("tm-cto"), "=tm-cto");
assert_eq!(exact_session_target("=tm-cto"), "=tm-cto");
assert_eq!(exact_session_target("tm:proj.0"), "=tm_proj_0");
}
#[test]
fn exact_window_target_appends_colon() {
assert_eq!(exact_window_target("tm-cto"), "=tm-cto:");
assert_eq!(exact_window_target("=tm-cto"), "=tm-cto:");
assert_eq!(exact_window_target("tm:proj:0"), "=tm_proj_0:");
}
#[test]
fn exact_targets_leave_immutable_ids_unchanged() {
for id in ["$0", "@12", "%6015"] {
assert!(is_immutable_id(id), "{id}");
assert_eq!(exact_session_target(id), id);
assert_eq!(exact_window_target(id), id);
}
for not_id in ["$", "%", "$x", "%1a", "tm-1", ""] {
assert!(!is_immutable_id(not_id), "{not_id:?}");
}
}
#[test]
fn exact_pane_target_keeps_ids_and_qualifies_specs() {
assert_eq!(exact_pane_target("s", "%7"), "%7");
assert_eq!(exact_pane_target("s", "0"), "=s:0");
assert_eq!(exact_pane_target("s", "1.2"), "=s:1.2");
}
#[test]
fn shell_attach_command_quotes_exact_target() {
assert_eq!(
shell_attach_command("tm-cto"),
"tmux attach-session -t '=tm-cto'"
);
assert_eq!(
shell_attach_command("a'b"),
r"tmux attach-session -t '=a'\''b'"
);
}
#[test]
fn empty_session_names_never_render_a_resolvable_target() {
for name in ["", "=", " ", "= "] {
assert!(check_session_name(name).is_err(), "{name:?}");
assert!(TmuxTarget::try_session(name).is_err(), "{name:?}");
assert!(TmuxTarget::session(name).validate().is_err(), "{name:?}");
assert_eq!(exact_session_target(name), "$", "{name:?}");
assert_eq!(exact_window_target(name), "%", "{name:?}");
assert_eq!(exact_pane_target(name, "0"), "%", "{name:?}");
assert_eq!(TmuxTarget::session(name).as_target(), "%", "{name:?}");
let kill = tmux_argv(&TmuxCommand::KillSession { name: name.into() });
assert_eq!(kill, ["kill-session", "-t", "$"], "{name:?}");
}
assert!(TmuxTarget::pane("", "%4").validate().is_ok());
assert!(TmuxTarget::try_session("tm-cto").is_ok());
}
#[test]
fn command_targets_refuse_empty_session_names() {
let bad = [
TmuxCommand::KillSession { name: "".into() },
TmuxCommand::HasSession { name: "=".into() },
TmuxCommand::ListPanes { name: " ".into() },
TmuxCommand::SendKeys {
target: TmuxTarget::session(""),
keys: "C-c".into(),
literal: false,
},
TmuxCommand::CapturePane {
target: TmuxTarget::session(""),
lines: None,
},
];
for cmd in &bad {
assert!(cmd.validate_targets().is_err(), "{cmd:?}");
}
assert!(
TmuxCommand::KillSession { name: "s".into() }
.validate_targets()
.is_ok()
);
assert!(TmuxCommand::ListSessions.validate_targets().is_ok());
}
#[test]
fn shell_targets_are_normalized_and_quoted() {
assert_eq!(shell_exact_session_target("tm:proj:0"), "'=tm_proj_0'");
assert_eq!(
shell_attach_command("tm:proj.0"),
"tmux attach-session -t '=tm_proj_0'"
);
}
#[test]
fn kill_and_has_session_argv_are_exact() {
let kill = tmux_argv(&TmuxCommand::KillSession {
name: "tm-cto".into(),
});
assert_eq!(kill, ["kill-session", "-t", "=tm-cto"]);
let has = tmux_argv(&TmuxCommand::HasSession {
name: "tm-cto".into(),
});
assert_eq!(has, ["has-session", "-t", "=tm-cto"]);
}
#[test]
fn new_session_argv_idempotent_with_workdir() {
let argv = tmux_argv(&TmuxCommand::NewSession {
name: "trusty-mpm-1".into(),
workdir: Some("/tmp/proj".into()),
idempotent: true,
command: None,
});
assert_eq!(
argv,
[
"new-session",
"-A",
"-d",
"-s",
"trusty-mpm-1",
"-c",
"/tmp/proj"
]
);
}
#[test]
fn new_session_argv_without_workdir_or_idempotent() {
let argv = tmux_argv(&TmuxCommand::NewSession {
name: "s".into(),
workdir: None,
idempotent: false,
command: None,
});
assert_eq!(argv, ["new-session", "-d", "-s", "s"]);
}
#[test]
fn new_session_argv_with_initial_command_is_trailing_positional() {
let argv = tmux_argv(&TmuxCommand::NewSession {
name: "debug-repl".into(),
workdir: Some("/tmp/proj".into()),
idempotent: false,
command: Some("bash -lc 'run-repl'".into()),
});
assert_eq!(
argv,
[
"new-session",
"-d",
"-s",
"debug-repl",
"-c",
"/tmp/proj",
"bash -lc 'run-repl'"
]
);
}
#[test]
fn send_keys_literal_argv() {
let argv = tmux_argv(&TmuxCommand::SendKeys {
target: TmuxTarget::session("s"),
keys: "claude --help".into(),
literal: true,
});
assert_eq!(argv, ["send-keys", "-t", "=s:", "-l", "claude --help"]);
}
#[test]
fn rename_session_argv() {
let argv = tmux_argv(&TmuxCommand::RenameSession {
old: "tm-old-01".into(),
new: "tm-new-01".into(),
});
assert_eq!(argv, ["rename-session", "-t", "=tm-old-01", "tm-new-01"]);
}
#[test]
fn send_keys_keyname_argv() {
let argv = tmux_argv(&TmuxCommand::SendKeys {
target: TmuxTarget::pane("s", "%1"),
keys: "Enter".into(),
literal: false,
});
assert_eq!(argv, ["send-keys", "-t", "%1", "Enter"]);
}
#[test]
fn send_keys_pane_target_is_bare_id() {
let argv = tmux_argv(&TmuxCommand::SendKeys {
target: TmuxTarget::pane("trusty-mpm-xyz", "%6015"),
keys: "claude --resume".into(),
literal: true,
});
let target_arg = &argv[argv.iter().position(|a| a == "-t").unwrap() + 1];
assert_eq!(target_arg, "%6015", "pane target must be the bare pane id");
assert!(
!target_arg.contains(':'),
"pane target must not be session-qualified: {target_arg}"
);
}
#[test]
fn capture_argv() {
let argv = tmux_argv(&TmuxCommand::CapturePane {
target: TmuxTarget::session("s"),
lines: Some(50),
});
assert_eq!(argv, ["capture-pane", "-t", "=s:", "-p", "-S", "-50"]);
let argv = tmux_argv(&TmuxCommand::CapturePane {
target: TmuxTarget::session("s"),
lines: None,
});
assert_eq!(argv, ["capture-pane", "-t", "=s:", "-p"]);
}
#[test]
fn list_sessions_uses_canonical_format() {
let argv = tmux_argv(&TmuxCommand::ListSessions);
assert_eq!(argv, ["list-sessions", "-F", SESSION_LIST_FORMAT]);
}
#[test]
fn list_windows_argv() {
let argv = tmux_argv(&TmuxCommand::ListWindows {
name: "work".into(),
});
assert_eq!(
argv,
["list-windows", "-t", "=work", "-F", WINDOW_LIST_FORMAT]
);
}
#[test]
fn list_panes_argv() {
let argv = tmux_argv(&TmuxCommand::ListPanes {
name: "work".into(),
});
assert_eq!(
argv,
["list-panes", "-s", "-t", "=work:", "-F", PANE_LIST_FORMAT]
);
}
#[test]
fn set_environment_argv() {
let argv = tmux_argv(&TmuxCommand::SetEnvironment {
session: "tmpm-brave-otter".into(),
key: "TM_MANAGED_SESSION_ID".into(),
value: "11111111-2222-3333-4444-555555555555".into(),
});
assert_eq!(
argv,
[
"set-environment",
"-t",
"=tmpm-brave-otter",
"TM_MANAGED_SESSION_ID",
"11111111-2222-3333-4444-555555555555"
]
);
}
#[test]
fn set_global_option_argv() {
let argv = tmux_argv(&TmuxCommand::SetGlobalOption {
name: "history-limit".into(),
value: "100000".into(),
});
assert_eq!(argv, ["set-option", "-g", "history-limit", "100000"]);
}
#[test]
fn start_server_argv() {
assert_eq!(tmux_argv(&TmuxCommand::StartServer), ["start-server"]);
}
#[test]
fn show_global_option_argv() {
let argv = tmux_argv(&TmuxCommand::ShowGlobalOption {
name: "history-limit".into(),
});
assert_eq!(argv, ["show-options", "-g", "-v", "history-limit"]);
}
#[test]
fn set_window_global_option_argv() {
let argv = tmux_argv(&TmuxCommand::SetWindowGlobalOption {
name: "alternate-screen".into(),
value: "off".into(),
});
assert_eq!(argv, ["set-option", "-wg", "alternate-screen", "off"]);
}
#[test]
fn show_window_global_option_argv_matches_set_scope() {
let set_scope = tmux_argv(&TmuxCommand::SetWindowGlobalOption {
name: ALTERNATE_SCREEN_OPTION.into(),
value: "off".into(),
})[1]
.clone();
let show_scope = tmux_argv(&TmuxCommand::ShowWindowGlobalOption {
name: ALTERNATE_SCREEN_OPTION.into(),
})[1]
.clone();
assert_eq!(set_scope, "-wg");
assert_eq!(show_scope, set_scope);
assert_eq!(
tmux_argv(&TmuxCommand::ShowWindowGlobalOption {
name: ALTERNATE_SCREEN_OPTION.into()
}),
["show-options", "-wg", "-v", "alternate-screen"]
);
}
#[test]
fn scrollback_option_commands_uses_configured_values() {
let cmds = scrollback_option_commands(50_000, true, DEFAULT_TMUX_ALTERNATE_SCREEN);
assert_eq!(cmds.len(), 3);
assert_eq!(
tmux_argv(&cmds[0]),
["set-option", "-g", "history-limit", "50000"]
);
assert_eq!(tmux_argv(&cmds[1]), ["set-option", "-g", "mouse", "on"]);
}
#[test]
fn scrollback_option_commands_mouse_off() {
let cmds = scrollback_option_commands(100_000, false, DEFAULT_TMUX_ALTERNATE_SCREEN);
assert_eq!(tmux_argv(&cmds[1]), ["set-option", "-g", "mouse", "off"]);
}
#[test]
fn scrollback_option_commands_alternate_screen_defaults_off() {
const { assert!(!DEFAULT_TMUX_ALTERNATE_SCREEN) };
let cmds = scrollback_option_commands(100_000, true, DEFAULT_TMUX_ALTERNATE_SCREEN);
assert_eq!(
tmux_argv(&cmds[2]),
["set-option", "-wg", "alternate-screen", "off"]
);
}
#[test]
fn scrollback_option_commands_alternate_screen_off_uses_window_scope() {
let cmds = scrollback_option_commands(100_000, true, false);
assert_eq!(
tmux_argv(&cmds[2]),
["set-option", "-wg", "alternate-screen", "off"]
);
}
#[test]
fn managed_session_commands_orders_options_before_new_session() {
let cmds = managed_session_commands("sess", Some("/tmp"), 100_000, true, false, true, None);
assert_eq!(cmds.len(), 4);
assert_eq!(
tmux_argv(&cmds[0]),
["set-option", "-g", "history-limit", "100000"]
);
assert_eq!(tmux_argv(&cmds[1]), ["set-option", "-g", "mouse", "on"]);
assert_eq!(
tmux_argv(&cmds[2]),
["set-option", "-wg", "alternate-screen", "off"]
);
assert_eq!(
tmux_argv(&cmds[3]),
["new-session", "-A", "-d", "-s", "sess", "-c", "/tmp"]
);
}
#[test]
fn managed_session_commands_idempotent_flag() {
let non_idempotent = managed_session_commands("sess", None, 100_000, true, true, false, None);
assert_eq!(
tmux_argv(&non_idempotent[3]),
["new-session", "-d", "-s", "sess"]
);
let idempotent = managed_session_commands("sess", None, 100_000, true, true, true, None);
assert_eq!(
tmux_argv(&idempotent[3]),
["new-session", "-A", "-d", "-s", "sess"]
);
}
#[test]
fn managed_session_commands_with_initial_command() {
let cmds = managed_session_commands(
"debug-repl",
None,
100_000,
true,
true,
false,
Some("run-repl"),
);
assert_eq!(
tmux_argv(&cmds[3]),
["new-session", "-d", "-s", "debug-repl", "run-repl"]
);
}
#[test]
fn default_history_limit_is_10_000() {
assert_eq!(DEFAULT_TMUX_HISTORY_LIMIT, 10_000);
let cmds = scrollback_option_commands(DEFAULT_TMUX_HISTORY_LIMIT, true, true);
assert_eq!(
tmux_argv(&cmds[0]),
["set-option", "-g", "history-limit", "10000"]
);
}