aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-02 14:24:33 +0300
committerGitHub <noreply@github.com>2026-09-02 14:24:33 +0300
commit6c0bb273d5d5405a00985621b17e36f8b4d64609 (patch)
treeceef5ea8adf337bf3c1e977b133e76cb763c6f1b /tests
parentcc88b3b8e5bb9f7d9f23ed6ae85a52fd7b5b9ed6 (diff)
feat: support independent multi-client tab views (#3526)
Diffstat (limited to 'tests')
-rw-r--r--tests/multi_client.rs53
-rw-r--r--tests/support/mod.rs12
2 files changed, 48 insertions, 17 deletions
diff --git a/tests/multi_client.rs b/tests/multi_client.rs
index ae642a22..514493cb 100644
--- a/tests/multi_client.rs
+++ b/tests/multi_client.rs
@@ -14,7 +14,7 @@ use portable_pty::{native_pty_system, Child, CommandBuilder, MasterPty, PtySize}
use serde_json::Value;
use support::{
cleanup_test_base, client_shell_handshake, drain_messages, register_runtime_dir,
- register_spawned_herdr_pid, send_detach, unregister_spawned_herdr_pid,
+ register_spawned_herdr_pid, send_client_shell_focus, send_detach, unregister_spawned_herdr_pid,
wait_for_client_shell_bootstrap, wait_for_message_variant, wait_for_message_variants,
CURRENT_ENDPOINT_PROTOCOL_GENERATION as CURRENT_PROTOCOL, SERVER_MESSAGE_PANE_SURFACE,
SERVER_MESSAGE_PANE_SURFACE_PATCH,
@@ -252,8 +252,29 @@ fn tty_size(socket: &Path, pane: &str, timeout: Duration) -> (u16, u16) {
panic!("pane did not report tty size: {}", pane_text(socket, pane));
}
+fn wait_for_tty_size(
+ socket: &Path,
+ pane: &str,
+ timeout: Duration,
+ expected: impl Fn((u16, u16)) -> bool,
+) -> (u16, u16) {
+ let deadline = Instant::now() + timeout;
+ loop {
+ let size = tty_size(
+ socket,
+ pane,
+ deadline.saturating_duration_since(Instant::now()),
+ );
+ if expected(size) {
+ return size;
+ }
+ assert!(Instant::now() < deadline, "unexpected tty size: {size:?}");
+ thread::sleep(Duration::from_millis(50));
+ }
+}
+
#[test]
-fn effective_size_uses_smallest_foreground_client_and_recovers_on_disconnect() {
+fn same_tab_geometry_follows_meaningful_client_activity() {
let _lock = test_lock();
let base = unique_test_dir();
let config = base.join("config");
@@ -264,26 +285,24 @@ fn effective_size_uses_smallest_foreground_client_and_recovers_on_disconnect() {
wait_for_socket(&api, Duration::from_secs(10));
wait_for_file(&clients, Duration::from_secs(10));
let pane = create_pane(&api, "effective-size");
- let mut large = shell(&clients, 120, 40);
+ let _large = shell(&clients, 120, 40);
let mut small = shell(&clients, 80, 24);
- let reduced = tty_size(&api, &pane, Duration::from_secs(5));
+ let initial = tty_size(&api, &pane, Duration::from_secs(5));
assert!(
- reduced.0 <= 24 && reduced.1 <= 80,
- "small ClientShell should determine effective size: {reduced:?}"
+ initial.0 > 24 && initial.1 > 80,
+ "a passive second connection must not steal geometry: {initial:?}"
);
+
+ send_client_shell_focus(&mut small, true).unwrap();
+ let reduced = wait_for_tty_size(&api, &pane, Duration::from_secs(5), |(rows, cols)| {
+ rows <= 24 && cols <= 80
+ });
+
send_detach(&mut small).unwrap();
drop(small);
- assert!(wait_for_message_variant(
- &mut large,
- Duration::from_secs(3),
- SERVER_MESSAGE_PANE_SURFACE
- )
- .unwrap());
- let restored = tty_size(&api, &pane, Duration::from_secs(5));
- assert!(
- restored.0 > reduced.0 && restored.1 > reduced.1,
- "size should recover: {reduced:?} -> {restored:?}"
- );
+ wait_for_tty_size(&api, &pane, Duration::from_secs(5), |(rows, cols)| {
+ rows > reduced.0 && cols > reduced.1
+ });
cleanup(server, base);
}
diff --git a/tests/support/mod.rs b/tests/support/mod.rs
index 68337ade..b2dae4be 100644
--- a/tests/support/mod.rs
+++ b/tests/support/mod.rs
@@ -21,6 +21,7 @@ pub const SERVER_MESSAGE_PANE_SURFACE: u32 = 13;
pub const SERVER_MESSAGE_SEMANTIC_NOTIFICATION: u32 = 14;
pub const SERVER_MESSAGE_PANE_SURFACE_PATCH: u32 = 19;
const CLIENT_MESSAGE_CLIENT_SHELL_PANE_INPUT: u32 = 13;
+const CLIENT_MESSAGE_CLIENT_SHELL_FOCUS: u32 = 18;
const CLIENT_MESSAGE_ENDPOINT_CONTROL: u32 = 20;
pub fn register_spawned_herdr_pid(pid: Option<u32>) {
@@ -387,6 +388,17 @@ pub fn send_client_shell_shift_enter(stream: &mut UnixStream, pane_id: &str) ->
.map_err(|e| format!("flush client shell key: {e}"))
}
+pub fn send_client_shell_focus(stream: &mut UnixStream, focused: bool) -> Result<(), String> {
+ let mut payload = encode_varint_u32(CLIENT_MESSAGE_CLIENT_SHELL_FOCUS);
+ payload.push(u8::from(focused));
+ stream
+ .write_all(&frame_message(&payload))
+ .map_err(|e| format!("write client shell focus: {e}"))?;
+ stream
+ .flush()
+ .map_err(|e| format!("flush client shell focus: {e}"))
+}
+
pub fn send_detach(stream: &mut UnixStream) -> Result<(), String> {
let detach_payload = encode_varint_u32(4);
let framed = frame_message(&detach_payload);